home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v10n04.arc / MBOOT.ASM < prev    next >
Assembly Source File  |  1991-02-01  |  174KB  |  5,232 lines

  1.               PAGE    ,132
  2. ;============================================================================
  3. ; MultiBoot - A program to allow PC Compatibles to have multiple
  4. ;             boot sequences.
  5. ;
  6. ;  Release history:
  7. ;            
  8. ;            1.0        Initial Release     PC Magazine Vol. 10, Num 4
  9. ;
  10. ;============================================================================
  11. ROOT_DIR        equ     2400h            ;Offset in of root dir
  12.  
  13. DATA_SEG1       equ     1790h            ;Holds IO.SYS data on copy
  14. DATA_SEG2       equ     2790h            ;Holds MSDOS.SYS data on copy
  15. FAT_SEGMENT1    equ     3790h            ;Holds 1st 64K of FAT
  16. FAT_SEGMENT2    equ     4790h            ;Holds 2nd 64K of FAT
  17.  
  18. NAME_LENGTH     equ     20            ;Length of session name 
  19. DTA_OFFSET    equ    80h
  20. SYSFILE_ATTR    equ    07h            ;Hidden, system, read only.
  21.  
  22. NEXT_ENTRY      equ     offset name2 - offset name1
  23. AUTO_OFFSET     equ     offset auto1 - offset name1
  24. CONFIG_OFFSET   equ     offset config1 - offset name1
  25. OSTYPE_OFFSET   equ     offset ostype1 - offset name1
  26.  
  27. NEXT_OSENTRY    equ     offset os_name2 - offset opsys_table
  28. OPSYS_TYPE      equ     offset os_boottype - offset opsys_table
  29.  
  30. MENU_SELECTED   equ     offset selected - offset menu_struc
  31. MENU_PROMPT     equ     offset prompt_loc - offset menu_struc
  32. MENU_TIMEOUT    equ     offset timeout - offset menu_struc
  33. MENU_FIRSTITEM  equ     offset firstitem - offset menu_struc
  34.  
  35. COLOR_NORM      equ     17h            ;Video attributes used for
  36. COLOR_HIGH      equ     71h            ;  menus.
  37. BW_NORM          equ     07h
  38. BW_HIGH          equ     70h
  39.  
  40. partition_ptrl  equ     word ptr [bp-60]
  41. partition_ptrh  equ     word ptr [bp-58]
  42. boot_disk       equ     byte ptr [bp-56]
  43. sectors2read    equ     byte ptr [bp-55]
  44. fat_sectorl     equ     word ptr [bp-54]
  45. fat_sectorh     equ     word ptr [bp-52]
  46. root_sectorl    equ     word ptr [bp-50]
  47. root_sectorh    equ     word ptr [bp-48]
  48. root_bytes      equ     word ptr [bp-46]
  49. data_startl     equ     word ptr [bp-44]
  50. data_starth     equ     word ptr [bp-42]
  51. read_buff       equ     word ptr [bp-36]
  52. old_choice      equ     word ptr [bp-34]
  53. bytes_per_clust equ     word ptr [bp-30]
  54. new_io_size    equ    word ptr [bp-24]
  55. new_dos_size    equ    word ptr [bp-22]
  56. low_fat_size    equ    word ptr [bp-20]
  57. hi_fat_size    equ    word ptr [bp-18]
  58.  
  59. bytes_per_sec   equ     word ptr [bp+0bh]
  60. sec_per_cluster equ     byte ptr [bp+0dh]
  61. reserved_sec    equ     word ptr [bp+0eh]
  62. number_of_fats  equ     byte ptr [bp+10h]
  63. root_size       equ     word ptr [bp+11h]
  64. total_sec       equ     word ptr [bp+13h]
  65. media_des_byte  equ     byte ptr [bp+15h]
  66. sec_per_fat     equ     word ptr [bp+16h]
  67. sec_per_track   equ     word ptr [bp+18h]
  68. number_of_heads equ     word ptr [bp+1ah]
  69. num_hidden_sec  equ     word ptr [bp+1ch]
  70. total_sec_long  equ     word ptr [bp+20h]
  71. drive_number       equ     word ptr [bp+24h]
  72. reserved        equ     word ptr [bp+25h]
  73. extended_flag   equ     word ptr [bp+26h]
  74. vol_serial      equ     word ptr [bp+27h]
  75. vol_name        equ     word ptr [bp+2bh]
  76.  
  77. ;============================================================================
  78. ; MBOOT - A substitute boot record to allow PC Compatibles to have
  79. ;           multiple boot sequences.
  80. ;
  81. ;  ***********************
  82. ;  !!!!    WARNING    !!!!
  83. ;  ***********************
  84. ;
  85. ; Tampering with this source code can cause boot failures, lost data,
  86. ; and sad times.  Be smart, just say no.
  87. ;
  88. ;============================================================================
  89.  
  90.             code    segment
  91.             assume  cs:code
  92.  
  93.             org     100h
  94. entry:           jmp     main
  95.  
  96. ooem_name        db     8 dup (" ")             ;These values will be modified
  97. obytes_per_sec   dw     ?                       ;  by the install routine.
  98. osec_per_cluster db     ?
  99. oreserved_sec    dw     ?
  100. onumber_of_fats  db     ?
  101. oroot_size       dw     ?
  102. ototal_sec       dw     ?
  103. omedia_des_byte  db     ?
  104. osec_per_fat     dw     ?
  105. osec_per_track   dw     ?
  106. onumber_of_heads dw     ?
  107.  
  108. onum_hidden_sec dw      ?                       ;Added in DOS 3.x
  109.             dw      ?
  110. ototal_sec_long dd      ?                       ;Added in DOS 4.x
  111. odrive_number   db      ?
  112. oreserved       db      ?
  113. oextended_flag  db      ?
  114. ovol_serial     dd      ?
  115. ovol_name       db      11 dup (?)
  116. oreserved1      db      8 dup (?)
  117.  
  118. ;-----------------------------------------------------------------------
  119. ; Start of boot code
  120. ;-----------------------------------------------------------------------
  121. bootcode        proc    near
  122.             assume  ds:code
  123.             cli                ;Disable interrupts
  124.             cld                             ;Set direction UP.
  125.             xor     bx,bx
  126.             mov     ax,790h
  127.             mov     ss,ax                   ;SS:SP = 790:0
  128.             mov     sp,bx
  129.             sti                ;Interrupts OK
  130.             mov     bp,100h                 ;Set up BP for data addressing
  131.         mov    partition_ptrl,si    ;Save partition table ptr
  132.  
  133.             mov     ds,bx                   ;DS = 0
  134.             mov     es,ax                   ;ES = 790h
  135.             mov     di,bp              ;Move boot code out of the way
  136.             mov     si,7c00h                
  137.             mov     cx,256
  138.             rep     movsw
  139.  
  140.             push    es
  141.             mov     ax,offset boot_1
  142.             push    ax
  143.             retf
  144. boot_1:
  145.             push    cs
  146.             pop     ds                      ;DS = 790h
  147.             mov     boot_disk,dl            ;Save boot_disk
  148.  
  149.             mov    ax,bx            ;BX = 0
  150.             mov     al,number_of_fats       ;Compute the sector of the
  151.             mul     sec_per_fat             ;  root directory.
  152.             mov     cx,reserved_sec
  153.             add     cx,num_hidden_sec
  154.             adc     dx,num_hidden_sec[2]
  155.             mov     fat_sectorl,cx
  156.             mov     fat_sectorh,dx
  157.             add     cx,ax
  158.             adc     dx,bx                   ;BX = 0
  159.             mov     root_sectorl,cx
  160.             mov     root_sectorh,dx
  161.             mov     data_startl,cx
  162.             mov     data_starth,dx
  163.             push    dx
  164.  
  165.             mov     ax,32                   ;Get length of dir entry
  166.             mul     root_size               ;Compute the size -in sectors-
  167.             mov     si,bytes_per_sec        ;  of the Root Directory.
  168.             add     ax,si
  169.             dec     ax
  170.             div     si
  171.             add     data_startl,ax
  172.             adc     data_starth,bx
  173.             mov     root_bytes,ax           ;Save size of root dir
  174.  
  175.             xchg    ax,cx
  176.             pop     dx
  177.             mov     bx,ROOT_DIR
  178.             call    read_disk
  179.             jc      boot_error
  180.  
  181.             mov     si,offset mboot_name
  182.             call    load_and_boot
  183.             call    print_line        ;Print lost MBOOT.SYS msg
  184.  
  185.             mov     si,offset lastboot_name ;If fail, try old boot record
  186.             call    load_and_boot
  187. boot_error:
  188.             push    si
  189.             mov     si,offset bootfail_msg
  190.             call    print_line
  191.             pop     si
  192.             call    print_line
  193.  
  194. boot_halt:      jmp     short boot_halt
  195. bootcode        endp
  196.  
  197. ;-----------------------------------------------------------------------
  198. ; Read disk / Write Disk
  199. ; Entry: DX,AX - Absolute sector to read/write
  200. ;        BX - address of buffer.
  201. ;        CL - Number of sectors to read
  202. ; Exit:  CF - Clear if read successful.
  203. ;-----------------------------------------------------------------------
  204. write_disk      proc    near
  205.             mov     ch,3                    ;BIOS write disk
  206.             jmp     short read_0
  207. write_disk      endp
  208.  
  209. read_disk       proc    near
  210.             mov     ch,2                    ;BIOS read disk
  211. read_0:
  212.             push    di
  213.             mov     sectors2read,cl         ;Save number of sectors to read
  214.             mov     si,ax                   ;Save starting sector to read
  215.             mov     di,dx
  216.             mov     read_buff,bx
  217. read_1:
  218. ;Compute the Cylinder, Head, and Sector to read.
  219.             mov     ax,si            ;Get logical sector
  220.             mov     dx,di
  221.         mov    bx,sec_per_track    ;Get sectors per track
  222.             div     bx
  223.             inc     dx
  224.  
  225.         inc    bx
  226.         cmp    cl,4            ;Never read more than 4
  227.         jb    read_2            ;  sectors
  228.         mov    cl,4
  229. read_2:
  230.         push    dx
  231.         add    dl,cl            ;Prevent a disk read across
  232.         cmp    dx,bx            ;  a track boundry.
  233.         pop    dx
  234.         jbe    read_21
  235.         dec    cl
  236.         jmp    short read_2
  237. read_21:
  238.             mov     bx,dx                   ;Save sector
  239.             push    cx                      ;Save sectors to read
  240.  
  241.             cwd
  242.             div     number_of_heads         ;Compute head and cylinder
  243.             xchg    ah,al                   ;Swap cyl low and high bytes
  244.             mov     cl,6
  245.             shl     al,cl                   ;Shift high cyl bits
  246.             xchg    cx,ax                   ;Copy cyl into CX
  247.             or      cl,bl                   ;Combine cyl with sector
  248.             mov     dh,dl                   ;Move head number
  249.             pop     ax
  250.             mov     bh,5                    ;Try to read 5 times.
  251. read_3:
  252.             push    bx
  253.             push    ax
  254.             mov     bx,read_buff
  255.             mov     dl,boot_disk            ;Get disk to read
  256.         push    ax            ;Save sectors read
  257.             int     13h                     ;Read/Write disk.
  258.         pop    ax            ;Get sectors read
  259.         xor    ah,ah
  260.             jc      read_4                  ;Error, try again.
  261.             pop     cx                      ;Restore read/write cmd
  262.             pop     bx                      ;Restore retry count
  263.  
  264.             add     si,ax                   ;Update starting sector
  265.             adc     di,0
  266.             sub     sectors2read,al         ;Sub from total sectors to read
  267.             mul     bytes_per_sec           ;Move read buffer pointer
  268.             add     read_buff,ax
  269.             mov     cl,sectors2read
  270.             cmp     cl,0
  271.             ja      read_1
  272.             clc
  273. read_exit:
  274.             pop     di
  275.             ret
  276. read_4:
  277.             xor     ax,ax                   ;Reset disk before reading
  278.             int     13h
  279.             pop     ax
  280.             pop     bx
  281.             dec     bh
  282.             jnz     read_3
  283.             mov     si,offset readerr_msg
  284.             stc
  285.             jmp     short read_exit
  286. read_disk       endp
  287. ;-----------------------------------------------------------------------
  288. ; Find file - Searches the root directory for a filename.
  289. ; Entry: SI - Ptr to file name to find
  290. ; Exit:  CF - Clear if found.
  291. ;        DI - If CF clear, ptr to entry containing file name.
  292. ;-----------------------------------------------------------------------
  293. find_file       proc    near
  294.             mov     cx,root_size            ;Get number of entries
  295.             mov     di,ROOT_DIR
  296. findfile_1:
  297.             push    cx
  298.             push    si
  299.             push    di
  300.             mov     cx,11                   ;Compare names in entry
  301.             repe    cmpsb
  302.             pop     di
  303.             pop     si
  304.             pop     cx
  305.             je      findfile_2
  306.             add     di,32                   ;Point to next entry
  307.             loop    findfile_1
  308.             stc
  309.             ret
  310. findfile_2:
  311.             clc
  312.             ret
  313. find_file       endp
  314. ;-----------------------------------------------------------------------
  315. ; Print Line
  316. ; Entry: SI - Ptr to string to print.
  317. ;-----------------------------------------------------------------------
  318. print_line      proc    near
  319.             lodsb
  320.             or      al,al
  321.             je      findfile_2
  322.             mov     ah,0eh
  323.             mov     bx,7
  324.             int     10h
  325.             jmp     short print_line
  326. print_line      endp
  327.  
  328. ;-----------------------------------------------------------------------
  329. ; CLUSTER2SECTOR - Convert cluster number into sector number.
  330. ; Entry: AX - Cluster to read
  331. ; Exit:  AX - Sector number
  332. ;        CX - Cluster size
  333. ;-----------------------------------------------------------------------
  334. cluster2sector  proc    near
  335.             dec     ax            ;Compensate for 1st to FAT
  336.             dec     ax            ;  entries not being used.
  337.             xor     cx,cx                   ;Compute the starting sector
  338.             mov     cl,sec_per_cluster
  339.             mul     cx                      ;CX, number of sectors to read
  340.             add     ax,data_startl        
  341.             adc     dx,data_starth
  342.             ret
  343. cluster2sector  endp
  344.  
  345. ;-----------------------------------------------------------------------
  346. ; LOAD FIRST - Reads the first cluster of a file.
  347. ; Entry: BX - Destination buffer
  348. ;        DI - Ptr to directory entry
  349. ;-----------------------------------------------------------------------
  350. load_first    proc    near
  351.             mov     ax,[di+1ah]             ;Get starting cluster
  352.             mov     di,ax                   ;Save starting cluster
  353.             call    cluster2sector          ;Read 1st cluster.
  354.             call    read_disk
  355.         ret
  356. load_first    endp
  357.  
  358. ;-----------------------------------------------------------------------
  359. ; Load and Boot
  360. ; Entry: SI - Ptr to file name to load and boot
  361. ; Exit:  This routine will not return if boot file found.
  362. ;        CF - Set if boot file not found.
  363. ;        SI - Offset of error message.
  364. ;-----------------------------------------------------------------------
  365. load_and_boot   proc    near
  366.             assume  cs:code,ds:code
  367.             call    find_file               ;Find filename in dir list
  368.             jnc     lab_1
  369. lab_error:
  370.             mov     di,offset bootfile      ;Copy name of boot file
  371.             mov     cx,11                   ;  not found.
  372.             rep     movsb
  373.             xor     ax,ax                   ;Terminate string
  374.             stosb
  375.             mov     si,offset mbootlost_msg
  376.             ret
  377. lab_1:
  378.             mov     bx,300h                 ;Offset to load extended boot
  379.         call    load_first        ;Read first cluster of file
  380.             jc      lab_error
  381.  
  382.             pop     ax                      ;Remove local return address
  383.  
  384.         mov    dl,boot_disk
  385.         mov    si,partition_ptrl
  386.             xor     ax,ax                   ;Set up expected segment config
  387.             push    ax
  388.             mov     ah,7ch
  389.             push    ax
  390.             retf
  391. load_and_boot   endp
  392.  
  393. ;-----------------------------------------------------------------------
  394. ; Data used by the Boot record.
  395. ;-----------------------------------------------------------------------
  396. mboot_name      db      "MBOOT   SYS"
  397. lastboot_name   db      "LASTBOOTBIN"
  398. bootfail_msg    db      "Boot Failure",13,10,0
  399. readerr_msg     db      "Disk Error",0
  400. mbootlost_msg   db      "Can",27h,"t find file "
  401. bootfile        =       $
  402.             org     2FEh
  403.             dw      0aa55h                  ;Boot record flag
  404.  
  405. ;============================================================================
  406. ;============================================================================
  407. ; This part of Multiboot is loaded by the boot record.
  408. ;============================================================================
  409. ;============================================================================
  410. boot_extend_start =     $
  411.             jmp     boot_extend
  412.         org    303h
  413. boot_ptr_array    =    $
  414. boot_data_ptr    dw    offset boot_data1 - offset boot_extend_start
  415. boot_data_size    dw    offset boot_data1_end - offset boot_data1
  416. boot_sess_ptr    dw    offset boot_array - offset boot_extend_start
  417. boot_sess_size    dw    offset boot_array_end - offset boot_array
  418. boot_ostab_ptr    dw    offset opsys_table - offset boot_extend_start
  419. boot_ostab_size    dw    offset opsys_table_end - offset opsys_table
  420. boot_version    dw    05h
  421.  
  422. boot_data1      =    $
  423. last_choice     dw      1                       ;Boot session currently active
  424. last_opsys      db      1                       ;Last operating system booted.
  425. last_DOS    db    1            ;Last DOS version booted
  426.  
  427. boot_default    db      0                       ;Default boot session
  428. boot_timeout    dw      0                       ;Time until default
  429. opsys_clusters    dw    0            ;Size of original op sys files
  430. time_stamp    dd    0            ;Time stamp to verify disk.
  431. boot_data1_end   =    $
  432.  
  433. fat_seg_low    dw    FAT_SEGMENT1
  434. fat_seg_high    dw    FAT_SEGMENT2
  435. fat_mask        dw      0
  436. fat_size    dw    0
  437. load_error    db    "Boot extend load error",13,10,0
  438. ;-------------------------------------------------------------------------
  439. ; GET FATTYPE - Determines if the FAT is 12 bit or 16 bit.
  440. ; Entry:    BP - Pointer to boot data structure.
  441. ; Exit:     fat_mask initialized
  442. ;-------------------------------------------------------------------------
  443. get_fattype    proc    near
  444.             mov     si,0fff8h               ;Assume 16 bit FAT
  445.             xor     dx,dx
  446.             mov     ax,total_sec
  447.             or      ax,ax                   ;If total sectors = 0, huge
  448.             jne     get_fattype_1           ;  partition.
  449.             mov     ax,word ptr total_sec_long
  450.             mov     dx,word ptr total_sec_long[2]
  451. get_fattype_1:
  452.             xor     cx,cx                   ;If more than 4087 clusters,
  453.             mov     cl,sec_per_cluster      ;  assume 16 bit FAT.
  454.             div     cx
  455.             cmp     ax,4087        
  456.             ja      get_fattype_2
  457.             mov     si,0ff8h                ;Set 12 bit FAT mask
  458. get_fattype_2:
  459.         mov    fat_mask,si        ;Save FAT mask
  460.         mov    fat_size,ax
  461.         ret
  462. get_fattype    endp
  463.  
  464. ;-------------------------------------------------------------------------
  465. ; GET FAT ENTRY - Finds a FAT entry from index
  466. ; Entry:    BP - Pointer to boot data structure.
  467. ;           DI - Entry into FAT table
  468. ; Exit:     DI - Next entry
  469. ;           CF - Clear if last entry
  470. ;-------------------------------------------------------------------------
  471. get_fat_entry    proc    near
  472.         push    bx
  473.         push    ds
  474.         push    es
  475.         mov    dx,fat_mask        ;Get FAT mask 
  476.         mov    es,fat_seg_high        ;Load DS and ES with segments
  477.         mov    ds,fat_seg_low         ;  containing the FAT table.
  478.  
  479.             mov     bx,di                   ;Copy index number
  480.         add    bx,di
  481.         mov    ax,ds:[bx]        ;Assume low segment of 16 bit
  482.         jnc    get_fat_entry_1        ;  FAT.
  483.         mov    ax,es:[bx]        ;CF set, high segment
  484. get_fat_entry_1:
  485.             or      dx,dx                   ;Test for 12 or 16 bit FAT
  486.             js      get_fat_entry_3
  487.         mov    bx,di
  488.             shr     di,1                    ;12 bit FAT
  489.             mov     ax,ds:[bx+di]
  490.             jnc     get_fat_entry_2
  491.             mov     cl,4                    ;If odd index, shift
  492.             shr     ax,cl
  493. get_fat_entry_2:
  494.             and     ah,0fh                  ;Clear top nibble
  495. get_fat_entry_3:
  496.         mov    di,ax            ;Copy entry data
  497.             cmp     ax,dx            ;See if last entry
  498.         pop    es
  499.         pop    ds
  500.         pop     bx
  501.         ret
  502. get_fat_entry     endp
  503.  
  504. ;-------------------------------------------------------------------------
  505. ; LOAD FILE1 - Loads a file by reading the FAT table (Skips first cluster)
  506. ; Entry:    BP - Pointer to boot data structure.
  507. ;     ES:BX - Destination buffer
  508. ;           DI - Entry into FAT table
  509. ; Exit:     CF - Set if error
  510. ;-------------------------------------------------------------------------
  511. load_file1    proc    near
  512. load_file_1:
  513.         call    get_fat_entry
  514.         jnc     load_file_exit
  515.             push    bx
  516.             call    cluster2sector          ;Read next cluster
  517.             call    read_disk
  518.             pop     bx
  519.             jc      load_file_exit1
  520.         add    bx,bytes_per_clust    ;Update read destination
  521.         jmp    short load_file_1
  522. load_file_exit:
  523.         clc
  524. load_file_exit1:
  525.         ret
  526. load_file1    endp
  527.  
  528.  
  529. debug_msg5    db    ".",0
  530.  
  531. ;====================================================================
  532. ; BOOT EXTEND 
  533. ; Entry: DL - Boot Disk
  534. ;        SI - Pointer to booted partition table entry
  535. ;        DI - Starting cluster for this file
  536. ;====================================================================
  537. boot_extend     proc    near
  538.             mov     ax,790h                 ;Reload CS and DS.
  539.             mov     ds,ax
  540.             mov     es,ax
  541.             push    ax
  542.             mov     ax,offset extend_load_0    
  543.             push    ax
  544.             retf
  545. ;
  546. ; Since MBOOT.SYS may be larger than one cluster, the FAT table must be read
  547. ; and interpeted.  This next section of code must reside in the first
  548. ; 512 bytes of MBOOT.SYS.
  549. ;
  550. extend_load_0:
  551.         mov    hi_fat_size,0
  552.             mov     ax,sec_per_fat        ;Compute size of FAT
  553.         mov    cx,ax
  554.         mul    bytes_per_sec
  555.         or    dx,dx            ;See if larger than 64K
  556.         je     extend_load_1        ;Compute the max number of
  557.         mov    dx,1            ;  sectors in 64K.
  558.         xor    ax,ax
  559.         div    bytes_per_sec
  560.         mov    cx,ax            ;Copy sectors to read
  561. extend_load_1:
  562.          mov    low_fat_size,cx
  563.         mov    ax,FAT_SEGMENT1
  564.         mov    es,ax
  565.         xor    bx,bx
  566.             mov     ax,fat_sectorl          ;Get starting sector of FAT 
  567.             mov     dx,fat_sectorh
  568.         push    cx
  569.             call    read_disk        ;Read FAT 
  570.         pop    cx
  571.             jc      extend_read_error
  572.  
  573.         mov    ax,cx            ;If FAT larger than 64K
  574.         sub    cx,sec_per_fat        ;  read remainder into second
  575.         jbe    extend_load_2        ;  segment.
  576.          mov    hi_fat_size,cx
  577.         mov    bx,FAT_SEGMENT2
  578.         mov    es,bx
  579.         xor    bx,bx
  580.         mov    dx,bx
  581.             add     ax,fat_sectorl          ;Get ptr to remainder of FAT
  582.             adc     dx,fat_sectorh
  583.             call    read_disk        ;Read FAT 
  584.             jc      extend_read_error        
  585. extend_load_2:
  586.         push    cs            ;Restore ES
  587.         pop    es
  588.         call    get_fattype        ;See if 12 or 16 bit fat
  589.             xor     ax,ax
  590.             mov     al,sec_per_cluster
  591.             mul     bytes_per_sec
  592.         mov    bytes_per_clust,ax    ;Save bytes per cluster
  593.         mov    bx,ax              ;BX = dest for file data.  Add
  594.         add    bx,300h            ;  size of boot rec + 100h
  595.         call    load_file1        ;Read remainder of MBOOT.SYS
  596.             jnc     extend_load_3
  597. extend_read_error:
  598.         mov    si,offset load_error    ;Indicate load error
  599.             jmp     boot_error
  600. ;
  601. ; MBOOT.SYS fully loaded.  Get on with displaying the menu.
  602. ;
  603. extend_load_3:
  604.         mov    screen_rows,25        ;Configure screen
  605.         mov    normal_attr,COLOR_NORM
  606.         mov    highlight_attr,COLOR_HIGH
  607.         xor    ax,ax
  608.         int    11h            ;Get screen type
  609.             mov     bx,0003h                ;Set video mode 3
  610.         test    ax,10h            ;See if color or BW
  611.         jz    boot_extend_00
  612.             mov     bx,0007h                ;Set video mode 7
  613.         mov    normal_attr,BW_NORM
  614.         mov    highlight_attr,BW_HIGH
  615. boot_extend_00:    
  616.             mov     ax,bx            ;Set video mode.
  617.             call    vidint
  618.             call    write_box               ;Write copyright box
  619. boot_extend_01:
  620.             xor     ax,ax
  621.             mov     al,boot_default         ;Copy defaults
  622.             push    bp
  623.             mov     bp,offset boot_menu
  624.             mov     [bp+MENU_SELECTED],al
  625.             cmp     al,0                    ;If no default, no timeout
  626.             je      extend_load_02
  627.             mov     ax,boot_timeout
  628. extend_load_02:
  629.             mov     [bp+MENU_TIMEOUT],ax
  630.             call    menu
  631.             pop     bp
  632.             cmp     bl,0                    ;If no choice, ask again.
  633.             je      boot_extend_01
  634.  
  635.             call    scroll_half        ;Clear screen
  636.  
  637.             cmp     bx,last_choice          ;See if the choice is the same
  638.             jne     boot_extend_11          ;  as last time.
  639.             jmp     boot_extend_boot    ;Yes, boot with old files.
  640. boot_extend_11:
  641.         push    bx
  642.         call    get_entry        ;Get ptr to new entry    
  643.         mov    di,bx
  644.         pop    bx
  645.             xchg    last_choice,bx          ;Save new choice, get last
  646.             mov     old_choice,bx           ;Save in case of write error
  647.             call    get_entry               ;Compute offset of old entry
  648.  
  649.         mov    al,[di+OSTYPE_OFFSET]    ;If the operating system is
  650.         cmp    al,last_opsys        ;  different from the last 
  651.         je    boot_extend_2        ;  one, read the os files.
  652.  
  653.         mov    bl,al            ;See if OS/2 or DOS op sys.
  654.         call    get_os_entry        
  655.         cmp    word ptr [di+OPSYS_TYPE],100h    ;If OS/2 skip file
  656.         jae    boot_extend_22            ;  copying.
  657.  
  658.         cmp    al,last_DOS        ;If last DOS version same, 
  659.         je     boot_extend_22        ;  skip file copy.
  660.  
  661.         push    ax            ;Tell user we are changing
  662.         push    bx            ;  the DOS files.
  663.         mov    si,offset change_os_msg
  664.         call    write_linenorm
  665.         pop    bx
  666.         pop    ax
  667.  
  668.         mov    last_DOS,al
  669.         call    load_os_files        ;Read the DOS system files
  670.         mov    si,offset read_os_error
  671.         jc     boot_extend_write_error1
  672.  
  673.         call    write_os_files        ;Write DOS sys files to disk
  674.         jc    boot_extend_write_error1
  675.         push    ax
  676.         xor    ax,ax
  677.         mov    cx,ax
  678.         mov    cl,number_of_fats
  679. boot_extend_21:
  680.         call    write_fat_table        ;Write updated FAT to disk
  681.         inc    ax
  682.         loop    boot_extend_21
  683.         pop    ax
  684. boot_extend_22:
  685.         push    ax
  686.         mov    bl,last_opsys        ;Rename the boot record file
  687.         call    make_os_names        ;  to the name in the os table
  688.         mov    di,si
  689.         mov    si,offset lastboot_name
  690.         call    rename_file
  691.         pop    bx            ;Get back the new op sys type        
  692.         mov    last_opsys,bl
  693.         call    make_os_names        ;Rename the new boot file to
  694.         call    rename_file        ;  LASTBOOT.SYS
  695.  
  696.             mov     bx,old_choice        ;Get prev session
  697.             call    get_entry               ;Compute offset of old entry
  698. boot_extend_2:
  699.             lea     di,[bx+AUTO_OFFSET]    ;Rename the current AUTOEXEC
  700.             mov     si,offset autoexec_name    ;  file to its old name
  701.             call    rename_file
  702.  
  703.             lea     di,[bx+CONFIG_OFFSET]    ;Rename the current CONFIG.SYS
  704.             mov     si,offset config_name    ;  file to its old name.
  705.             call    rename_file
  706.  
  707.             mov     bx,last_choice          ;Rename saved files to
  708.             call    get_entry               ;  CONFIG.SYS and AUTOEXEC.BAT
  709.             lea     si,[bx+AUTO_OFFSET]     ;Start with AUTOEXEC.BAT
  710.             mov     di,offset autoexec_name
  711.             call    rename_file
  712.  
  713.             lea     si,[bx+CONFIG_OFFSET]   ;Now rename CONFIG.SYS
  714.             mov     di,offset config_name
  715.             call    rename_file
  716. boot_extend_3:
  717.             mov     ax,root_sectorl         ;Write the Root directory back
  718.             mov     dx,root_sectorh         ;  to the disk.
  719.             mov     bx,ROOT_DIR
  720.             mov     cx,root_bytes           ;Get size of root directory
  721.             call    write_disk
  722.             jnc     boot_extend_4           ;If write error,  Boot last
  723. boot_extend_write_error:
  724.             mov     si,offset boot_extend_err  ;  boot record.
  725. boot_extend_write_error1:
  726.             call    write_linenorm
  727.             mov     bx,old_choice
  728.             jmp     short boot_extend_boot
  729. boot_extend_4:
  730.             mov     si,offset mboot_name    ;Find MBOOT again in dir list
  731.             call    find_file
  732.             jc      boot_extend_write_error
  733.             mov     ax,[di+1ah]             ;Get starting cluster
  734.             mov     bx,300h
  735.             call    cluster2sector        ;Update the MBOOT boot table
  736.             call    write_disk
  737.             jc      boot_extend_write_error
  738.         mov    bx,last_choice
  739. boot_extend_boot:
  740.         call    get_entry        ;Print message to identify 
  741.         push    bx            ;  the session booting
  742.         mov    si,bx            
  743.         mov    di,offset boot_sess_msg1
  744.         mov    cx,NAME_LENGTH+1
  745.         rep    movsb
  746.         mov    si,offset boot_sess_msg    
  747.         call    write_linenorm
  748.         pop    bx
  749.  
  750.         mov    bl,[bx+OSTYPE_OFFSET]    ;Print message to identify 
  751.         call    get_os_entry        ;  operating system booting.
  752.         mov    si,offset boot_os_msg1
  753.         xchg    si,di
  754.         mov    cx,9
  755.         rep    movsb
  756.         mov    si,offset boot_os_msg
  757.         call    write_linenorm
  758.  
  759.         mov    dx,0d00h        ;Row 13, Column 0
  760.             call    set_cursor
  761.         mov    si,offset lastboot_name    ;Boot operating system.
  762.             call    load_and_boot
  763.             jmp     boot_halt        ;If this returns, halt
  764. boot_extend     endp
  765.  
  766. ;--------------------------------------------------------------------
  767. ; MENU querys the user menu selection.
  768. ; Entry: BP - Pointer to menu structure.
  769. ; Exit:  BX - Menu item selected.
  770. ;--------------------------------------------------------------------
  771. menu            proc    near
  772.             mov     last_timeout,0
  773.             mov     dx,[bp+MENU_TIMEOUT]    ;Point to timeout line
  774.             mov     timeout_value,dx        ;Copy timeout value
  775.             or      dx,dx                   ;If 0, no timeout
  776.             je      menu_wrtprompt
  777.             mov     si,offset timeout_str   ;Ptr to timeout string
  778.             call    write_linenorm
  779.  
  780.             xor     ax,ax                   ;Read system timer
  781.             int     1ah
  782.             add     dx,timeout_value        ;Set timeout value
  783.             mov     timeout_value,dx
  784. menu_wrtprompt:
  785.             mov     dx,[bp+MENU_PROMPT]     ;Write menu prompt
  786.             mov     si,offset prompt_text
  787.             call    write_line_at
  788. key_loop:
  789.             call    write_menu              ;Write menu choices
  790. key_loop_1:
  791.             mov     ax,timeout_value
  792.             cmp     ax,0                    ;If timout not disabled, print
  793.             jne     key_1                   ;  time remaining.
  794.             cmp     ax,last_timeout
  795.             je      key_2
  796.             mov     last_timeout,ax
  797.             mov     si,offset timetext1
  798.             call    write_linenorm
  799.             jmp     short key_2
  800. key_1:
  801.             xor     ax,ax                   ;Read system timer
  802.             int     1ah
  803.             mov     ax,timeout_value
  804.             sub     ax,dx                   ;Subtract current time
  805.             ja      key_11            ;If no time, exit with 
  806.             jmp     key_quit        ;  carry.
  807. key_11:
  808.             mov     cx,18
  809.             xor     dx,dx
  810.             div     cx
  811.             inc     ax
  812.             cmp     ax,last_timeout
  813.             je      key_2
  814.             mov     last_timeout,ax
  815.             mov     dx,173ch                ;Write time remaining
  816.             call    hex2asc
  817.         mov    dx,1a00h        ;Hide cursor
  818.         call    set_cursor
  819. key_2:
  820.         cmp    no_DOS_flag,0
  821.         je    key_3
  822.         int    28h            ;Call DOS idle
  823. key_3:
  824.         call    get_key            ;Get key from keyboard
  825.             jz      key_loop_1        ;No key available, loop
  826.  
  827.             cmp     al,0dh                  ;If CR, exit.
  828.             je      key_exit
  829.             cmp     al,27                   ;If ESC, quit.
  830.             je      key_quit
  831.             cmp     al,3                    ;If Ctl-C, quit.
  832.             je      key_quit
  833.  
  834.             cmp     al,31h                  ;If valid number jump
  835.             jb      key_down_0              ;  directly to selection.
  836.             cmp     al,39h
  837.             ja      key_down_0
  838.             sub     al,30h
  839.             call    check_valid             ;See if selection valid
  840.             jc      key_loop_1              ;No, get another key
  841.             jmp     short key_loop_2
  842. key_down_0:
  843.             cmp     al,9                    ;Tab
  844.             je      key_down_1
  845.             cmp     ah,4dh                  ;Right
  846.             je      key_down_1
  847.             cmp     ah,50h                  ;Down
  848.             jne     key_up_1
  849. key_down_1:
  850.             mov     al,[bp+MENU_SELECTED]
  851. key_down_2:
  852.             inc     al
  853.             cmp     al,[bp]
  854.             jbe     key_down_3
  855.             mov     al,1
  856. key_down_3:
  857.             call    check_valid             ;See if selection valid
  858.             jc      key_down_2
  859.             jmp     short key_loop_2
  860. key_up_1:
  861.             cmp     ax,0f00h                ;Back Tab
  862.             je      key_up_2
  863.             cmp     ah,4bh                  ;Left
  864.             je      key_up_2
  865.             cmp     ah,48h                  ;Up
  866.             je      key_up_2
  867.             jmp     key_loop_1
  868. key_up_2:
  869.             mov     al,[bp+MENU_SELECTED]
  870. key_up_3:
  871.             sub     al,1
  872.             ja      key_loop_2
  873.             mov     al,[bp]
  874. key_loop_2:
  875.             call    check_valid             ;See if selection valid
  876.             jc      key_up_3
  877.             mov     [bp+MENU_SELECTED],al
  878.             mov     timeout_value,0         ;Disable timeout
  879.             jmp     key_loop
  880. key_exit:            
  881.             clc
  882. key_exit1:
  883.             mov    bh,0
  884.             mov     bl,[bp+MENU_SELECTED]   ;Get menu item selected
  885.             ret
  886. key_quit:
  887.             stc
  888.             jmp     short key_exit1
  889. menu            endp
  890.  
  891. ;--------------------------------------------------------------------
  892. ; GET KEY  gets a key from the keyboard.
  893. ; Exit:  AX - key returned
  894. ;        ZF - Set if no key
  895. ;--------------------------------------------------------------------
  896. get_key         proc    near
  897.             mov     ah,1
  898.             int     16h                     ;Check for key
  899.             jz      get_key_1
  900.             mov     ah,0
  901.             int     16h                     ;Get key
  902.         or    ax,ax
  903. get_key_1:
  904.         ret
  905. get_key        endp
  906.  
  907. ;--------------------------------------------------------------------
  908. ; FETCH KEY  waits for and gets a key from the keyboard
  909. ; Exit:  AX - key returned
  910. ;--------------------------------------------------------------------
  911. fetch_key       proc    near
  912.         int    28h            ;Call DOS idle
  913.         call    get_key            ;Read a key from the keyboard
  914.         jz    fetch_key
  915.         ret
  916. fetch_key    endp
  917.  
  918. ;--------------------------------------------------------------------
  919. ; CHECK VALID determines if a menu selection is valid.
  920. ; Entry: BP - Pointer to menu structure.
  921. ;        AL - Menu selection
  922. ; Exit:  CF - Clear if valid selection
  923. ;--------------------------------------------------------------------
  924. check_valid     proc    near
  925.             push    ax
  926.             push    di
  927.             dec     al
  928.             cmp     al,[bp]                 ;See if beyond choices
  929.             ja      check_valid_bad
  930.             xor     ah,ah                   ;Convert selection into
  931.             shl     ax,1                    ;  index into menu structure
  932.             shl     ax,1
  933.             lea     di,[bp+MENU_FIRSTITEM]  ;Get ptr to 1st item
  934.             add     di,ax
  935.             mov     si,[di+2]               ;Get location of string
  936.             or      al,[si]                 ;If 1st byte > 80h, disabled
  937.             js      check_valid_bad         ;  item.
  938.             clc
  939. check_valid_exit:
  940.             pop     di
  941.             pop     ax
  942.             ret
  943. check_valid_bad:
  944.             stc
  945.             jmp     short check_valid_exit
  946. check_valid     endp
  947.  
  948. ;--------------------------------------------------------------------
  949. ; WRITE MENU displays the choices on the screen.
  950. ; Entry: BP - Pointer to menu structure.
  951. ;--------------------------------------------------------------------
  952. write_menu      proc    near
  953.             xor     cx,cx
  954.             mov     cl,[bp]                 ;Get number of choices
  955.             xor     bx,bx
  956.             lea     di,[bp+MENU_FIRSTITEM]  ;Get ptr to 1st item
  957. write_menu_1:
  958.             inc     bh                      ;Inc menu item counter
  959.  
  960.             mov     si,[di+2]               ;Get location of string
  961.             cmp     byte ptr [si],80h       ;If 1st byte > 80h, disabled
  962.             jae     write_menu_3            ;  item, don't print.
  963.  
  964.             mov     dx,[di]                 ;Get location of item
  965.             mov     al,bh                   ;Print menu item number
  966.             call    printnum
  967.  
  968.             add     dl,4
  969.             mov     si,[di+2]               ;Get location of string
  970.             cmp     bh,[bp+MENU_SELECTED]   ;If selected, use highlight
  971.             jne     write_menu_2            ;  attribute.
  972.             call    write_line_hi
  973.             jmp     short write_menu_3
  974. write_menu_2:
  975.             call    write_line_at
  976. write_menu_3:
  977.             add     di,4                    ;Point to next item
  978.             loop    write_menu_1
  979.  
  980.             mov     dx,[bp+MENU_PROMPT]
  981.             add     dl,8
  982.         call    set_cursor        ;Set cursor pos
  983.  
  984.             mov     al,[bp+MENU_SELECTED]   ;Get current selection
  985.             or      al,al
  986.             je      write_menu_exit
  987.             add     al,30h
  988.  
  989.             mov     ah,0ah                  ;BIOS Write Char
  990.             mov     cx,1                    ;1 character
  991.         xor    bx,bx
  992.             call    vidint
  993. write_menu_exit:
  994.             ret
  995. write_menu      endp
  996.  
  997. ;--------------------------------------------------------------------
  998. ; GETENTRY - Computes the offset of a boot array entry given the
  999. ;            entry number
  1000. ; Entry: BL - Entry number
  1001. ; Exit:  BX - Offset of that entry
  1002. ;--------------------------------------------------------------------
  1003. get_entry       proc    near
  1004.             mov     ax,offset boot_array    
  1005. get_entry1:
  1006.         push    ax            ;Save start of table
  1007.             dec     bx
  1008.             mov     al,NEXT_ENTRY           ;Multiply the size of
  1009.             mul     bl                      ;  each entry by the
  1010.             pop     bx                      ;  number then add the
  1011.             add     bx,ax                   ;  starting offset.
  1012.             ret
  1013. get_entry       endp
  1014.  
  1015. ;--------------------------------------------------------------------
  1016. ; GET OS ENTRY - Computes offset of entry in the op sys table.
  1017. ; Entry: BL - Operating system number. 1 - 4
  1018. ; Exit:  DI - Pointer to entry in op sys table.
  1019. ;--------------------------------------------------------------------
  1020. get_os_entry    proc    near
  1021.         push    ax
  1022.         push    bx
  1023.         xor    bh,bh
  1024.         dec    bl
  1025.         mov    al,NEXT_OSENTRY
  1026.         mul    bl
  1027.         add    ax,offset opsys_table
  1028.         mov    di,ax
  1029.         pop    bx
  1030.         pop    ax
  1031.         ret
  1032. get_os_entry    endp
  1033.  
  1034. ;--------------------------------------------------------------------
  1035. ; LOAD_FILE - Computes offset of entry in the op sys table.
  1036. ; Entry: ES:BX - Destination buffer
  1037. ;           DI - Ptr to directory table entry 
  1038. ;           BP - Boot data ptr
  1039. ;--------------------------------------------------------------------
  1040. load_file    proc    near
  1041.         push    bx
  1042.         call    load_first
  1043.         pop    bx
  1044.         add    bx,bytes_per_clust
  1045.         call    load_file1
  1046.         ret
  1047. load_file    endp
  1048.  
  1049. ;--------------------------------------------------------------------
  1050. ; LOAD_OS_FILES - Reads the operating system files into memory.
  1051. ; Entry: AL - Operating system number
  1052. ;        BP - Boot data ptr
  1053. ;--------------------------------------------------------------------
  1054. load_os_files    proc    near
  1055.         push    ax
  1056.         push    bx
  1057.         mov    bl,al
  1058.         call    make_os_names        ;Make op sys names
  1059.         add    si,11            ;Point to IO.SYS name
  1060.         call    find_file        ;Find the filename
  1061.         jc    load_os_files_exit
  1062.         mov    cx,[di+1ch]        ;Read file size
  1063.         mov    new_io_size,cx
  1064.         push    di
  1065.         add    si,11            ;Point to MSDOS.SYS
  1066.         call    find_file        ;Find the filename
  1067.         mov    si,di
  1068.         pop    di
  1069.         jc    load_os_files_exit
  1070.         mov    cx,[si+1ch]        ;Read file size
  1071.         mov    new_dos_size,cx
  1072.         
  1073.         mov    ax,DATA_SEG1
  1074.         mov     es,ax
  1075.         xor    bx,bx
  1076.         push    si
  1077.         call    load_file        ;Read IO.SYS
  1078.         pop    di
  1079.         jc    load_os_files_exit
  1080.         mov    ax,DATA_SEG2
  1081.         mov     es,ax
  1082.         xor    bx,bx
  1083.         call    load_file        ;Read MSDOS.SYS        
  1084. load_os_files_exit:
  1085.         push    cs            ;Restore ES
  1086.         pop    es
  1087.         pop    bx
  1088.         pop    ax
  1089.         ret
  1090. load_os_files    endp
  1091.  
  1092. ;--------------------------------------------------------------------
  1093. ; WRITE_OS_FILES - Writes the operating system files onto the disk.
  1094. ; Entry: BP - Boot data ptr
  1095. ;        AL - Operating system number
  1096. ;--------------------------------------------------------------------
  1097. write_os_files    proc    near
  1098.         push    ax
  1099.         push    bx
  1100.  
  1101.         mov    bx,ax            ;Copy os number
  1102.         call    get_os_entry
  1103.         mov    cx,[di+OPSYS_TYPE]    ;Get os config    
  1104.  
  1105.         cmp    cx,50h             
  1106.         je    write_os_files_0
  1107.         mov    ax,1            ;At least 1 cluster needed
  1108.          cmp    cx,40h             ;  for DOS 4 type os
  1109.          jae    write_os_files_02
  1110.  
  1111.         mov    ax,new_io_size        ;Get clusters needed for
  1112.         xor    dx,dx            ;  files.
  1113.         div    bytes_per_clust        
  1114.         inc    ax
  1115.         push    ax            ;Save clusters for IO.SYS
  1116.  
  1117.         xor    ax,ax
  1118.         cmp    cx,30h            ;If DOS 3 type os, only IO.SYS
  1119.         jae    write_os_files_01    ;  size needs to be checked
  1120.         mov    ax,new_dos_size        
  1121.         xor    dx,dx
  1122.         div    bytes_per_clust        
  1123.         inc    ax
  1124. write_os_files_01:
  1125.         pop    dx            ;Get IO.SYS clusters needed
  1126.         add    ax,dx
  1127. write_os_files_02:
  1128.         push    ax            ;Save clusters needed
  1129.         push    bx
  1130.         call    check_fat        ;See if enough room for opsys
  1131.         pop    bx            ;  files.
  1132.         pop    dx            
  1133.         cmp    dx,cx
  1134.         mov    si,offset no_room_error
  1135.         ja    write_os_files_err1
  1136. write_os_files_0:
  1137.         mov    cx,new_io_size        ;Get size of new IO.SYS
  1138.         add    di,9             ;Point to IO.SYS name
  1139.         mov    si,di            ;Copy entry in op sys table
  1140.  
  1141.         mov    di,ROOT_DIR        ;Get ptr to root dir
  1142.         push    cx
  1143.         push    di
  1144.         call    clear_file        ;Remove IO.SYS from FAT
  1145.         add    di,20h            ;Point to next file
  1146.         call    clear_file        ;Remove MSDOS.SYS from FAT
  1147.         call    clean_fat        ;Remove any bad cluster flags
  1148.         
  1149.         mov    ax,DATA_SEG1        ;Get seg of IO.SYS data
  1150.         mov    es,ax
  1151.         mov    dx,1            ;Look for 1st free cluster.
  1152.         call    find_free_clust
  1153.         mov    dx,di        
  1154.         pop    di
  1155.         pop    cx
  1156.         call    store_os_file        ;Write IO.SYS to disk
  1157.         jc    write_os_files_exit
  1158.  
  1159.         add    di,20h            ;Point to next dir entry
  1160.         add    si,11            ;Point to MSDOS.SYS name
  1161.  
  1162.         mov    cx,new_dos_size        ;Get size of new MSDOS.SYS    
  1163.         mov    ax,DATA_SEG2        ;Get seg of MSDOS.SYS data
  1164.         mov    es,ax
  1165.         call    store_os_file        ;Write MSDOS.SYS to disk
  1166.         jc    write_os_files_exit
  1167.  
  1168.         mov    bx,opsys_clusters    ;Get number of sys sectors
  1169.         inc    bx
  1170.         mov    di,dx
  1171.         mov    ax,0fff7h        ;Bad sector flag
  1172.         cmp    bx,di
  1173.         jb    write_os_files_2
  1174. write_os_files_1:
  1175.         call    write_fat_entry        ;Fill in empty sectors with
  1176.         inc    di            ;  bad sector flags.
  1177.         cmp    bx,di
  1178.         jae    write_os_files_1
  1179. write_os_files_2:
  1180.         clc
  1181. write_os_files_exit:
  1182.         push    cs            ;Restore ES
  1183.         pop    es
  1184.         pop    bx
  1185.         pop    ax
  1186.         ret
  1187. write_os_files_err:
  1188.         mov    si,offset write_os_error
  1189. write_os_files_err1:
  1190.         stc
  1191.         jmp    short write_os_files_exit
  1192. write_os_files    endp
  1193.  
  1194. ;-----------------------------------------------------------------------
  1195. ; STORE OS FILE - Writes an operating system file to the disk
  1196. ; Entry: DX - Starting Cluster of file
  1197. ;        CX - Size of file
  1198. ;        SI - New file name
  1199. ;        DI - Ptr to directory entry
  1200. ;        ES - Segment of file data
  1201. ; Exit:     DX - Next free cluster
  1202. ;     CF - Set if error
  1203. ;-----------------------------------------------------------------------
  1204. store_os_file    proc    near
  1205.         push    di
  1206.         push    si
  1207.         push    es
  1208.         push    ds
  1209.         pop    es
  1210.         push    di            ;First, copy new name to
  1211.         push    cx            ;  dir entry. 
  1212.         mov    cx,11            
  1213.         rep    movsb
  1214.         pop    cx
  1215.         pop    di
  1216.         pop    es
  1217.  
  1218.         mov    [di+1Ah],dx        ;Save new starting cluster
  1219.         mov    [di+1Ch],cx        ;Save size in dir entry
  1220.         xor    bx,bx            ;Start at beginning of buffer
  1221. store_os_file_1:
  1222.         mov    ax,dx            ;Copy cluster to write
  1223.         push    bx
  1224.         push    cx
  1225.         push    dx
  1226.         call    cluster2sector        ;Convert to sector number
  1227.         call    write_disk        ;Write cluster to disk
  1228.         pop    dx
  1229.         pop    cx
  1230.         pop    bx
  1231.         add    bx,bytes_per_clust    ;Update read dest
  1232.         sub    cx,bytes_per_clust    ;Sub bytes  written from size
  1233.         ja    store_os_file_11
  1234.         mov    di,dx            ;Get new cluster
  1235.         mov    ax,-1            ;Write -1 to FAT entry to
  1236.         call    write_fat_entry        ;  indicate end of file.
  1237.         call    find_free_clust        ;Get next free cluster
  1238.         mov    dx,di            ;Copy ptr to free cluster
  1239. store_os_file_exit:
  1240.         pop    si
  1241.         pop    di
  1242.         ret
  1243. store_os_file_11:
  1244.         call    find_free_clust        ;Get next free cluster
  1245.         jc    store_os_file_exit
  1246.         mov    ax,di            ;Copy new FAT entry
  1247.         xchg    di,dx            ;Xchg old, new FAT entries    
  1248.         call    write_fat_entry        ;Write new cluster to old FAT
  1249.         jmp    short store_os_file_1    ;  entry.  Loop back for more.
  1250. store_os_file    endp
  1251.  
  1252. ;-----------------------------------------------------------------------
  1253. ; FIND FREE CLUST - Finds the next free cluster in the FAT
  1254. ; Entry: DX - Current cluster
  1255. ; Exit:     DI - Next free cluster
  1256. ;        CF - Set if no free clusters
  1257. ;-----------------------------------------------------------------------
  1258. find_free_clust    proc    near
  1259.         push    dx            
  1260. find_free_clust_1:
  1261.         inc    dx            ;First, check to see if at 
  1262.         cmp    fat_size,dx        ;  end of FAT.
  1263.         jb     find_free_clust_exit
  1264.  
  1265.         mov    di,dx            ;Scan through FAT to find next
  1266.         push    dx            ;  entry with 0, indicating
  1267.         call    get_fat_entry        ;  free cluster.    
  1268.         pop    dx
  1269.         or     di,di            ;See if cluster = 0 -> free
  1270.         jne    find_free_clust_1    ;No, keep looking
  1271.         mov    di,dx            ;Copy free cluster 
  1272.         clc
  1273. find_free_clust_exit:
  1274.         pop    dx
  1275.         ret
  1276. find_free_clust    endp
  1277.  
  1278. ;-----------------------------------------------------------------------
  1279. ; CHECK FAT - Counts the number of consecutive clusters at the start of
  1280. ;             the disk.
  1281. ; Exit:     CX - Count of available clusters.
  1282. ;-----------------------------------------------------------------------
  1283. check_fat     proc    near
  1284.         push    di
  1285.         mov    di,ROOT_DIR
  1286.         mov    bx,[di+1Ah]        ;Get starting cluster.  If not
  1287.         call    get_fat_chain        ;  consecutive clusters, skip
  1288.         jc    check_fat_1        ;  msdos.sys check.
  1289.         inc    bx
  1290.         mov    si,bx            ;Save ending cluster
  1291.         add    di,20h            ;Point to MSDOS.SYS entry
  1292.         mov    bx,[di+1Ah]        ;Get starting cluster
  1293.         cmp    si,bx
  1294.         jne    check_fat_6    
  1295.         call    get_fat_chain
  1296.         add    cx,si            ;Sum consec clusters.
  1297. check_fat_1:
  1298.         inc    bx
  1299.         mov    ax,fat_mask        ;Convert FAT mask into bad
  1300.         mov    al,0f7h            ;  sector detector
  1301. check_fat_2:
  1302.         mov    di,bx            ;Copy ptr to last FAT entry
  1303.         push    cx
  1304.         push    ax            ;Count the number of bad
  1305.         call    get_fat_entry        ;  sectors at the end of 
  1306.         pop    ax            ;  the system files.
  1307.         pop    cx
  1308.         or    di,di            ;See if sector free.
  1309.         je    check_fat_3
  1310.         cmp    di,ax            ;See if sector marked bad
  1311.         jne    check_fat_4
  1312. check_fat_3:
  1313.         inc    bx            ;Inc FAT pointer
  1314.         inc    cx            ;Inc Count
  1315.         jmp    short check_fat_2
  1316. check_fat_4:
  1317.         clc
  1318. check_fat_5:
  1319.         pop    di
  1320.             ret
  1321. check_fat_6:
  1322.         stc
  1323.         jmp    short check_fat_1
  1324. check_fat    endp
  1325.  
  1326. ;-----------------------------------------------------------------------
  1327. ; CLEAN FAT - Removes bad cluster markers used to reserve clusters.
  1328. ;-----------------------------------------------------------------------
  1329. clean_fat    proc    near
  1330.         mov    di,2            ;Start at cluster 2
  1331.         mov    bx,fat_mask
  1332.         and    bl,0f7h            ;Create Bad entry mask
  1333.         or    bl,0f7h
  1334. clean_fat_1:
  1335.         push    di
  1336.         call    get_fat_entry        ;See if entry marked bad
  1337.         cmp    di,bx
  1338.         pop    di
  1339.         jne    clean_fat_2        ;No, skip write.
  1340.         xor    ax,ax    
  1341.         call    write_fat_entry        ;Clear entry
  1342. clean_fat_2:
  1343.         inc    di            ;Point to next entry
  1344.         mov    ax,opsys_clusters
  1345.         add    ax,2
  1346.         cmp    di,ax
  1347.         jbe    clean_fat_1
  1348.         ret
  1349. clean_fat    endp
  1350.  
  1351. ;-----------------------------------------------------------------------
  1352. ; GET FAT CHAIN - Follows a FAT chain for a file.
  1353. ; Entry: BX - Ptr to start of chain
  1354. ; Exit:  CX - Count of consecutive clusters
  1355. ;        BX - Last entry in FAT table.
  1356. ;        CF - Set if file not in consecutive clusters
  1357. ;-----------------------------------------------------------------------
  1358. get_fat_chain    proc    near
  1359.         push    di
  1360.         xor    cx,cx
  1361.         mov    di,bx
  1362. get_fat_chain_1:
  1363.         inc    cx
  1364.         mov    bx,di            ;Copy FAT entry ptr
  1365.         push    cx
  1366.         call    get_fat_entry
  1367.         pop    cx
  1368.         mov    ax,bx
  1369.         jnc     get_fat_chain_2        ;CF = 0, last entry
  1370.         sub    bx,di            ;See if consecutive
  1371.         cmp    bx,-1
  1372.         je    get_fat_chain_1
  1373.         stc
  1374. get_fat_chain_2:
  1375.         mov    bx,ax            ;Get back last FAT entry
  1376.         pop    di
  1377.             ret
  1378. get_fat_chain    endp
  1379.  
  1380. ;-------------------------------------------------------------------------
  1381. ; CLEAR FILE - Removes the FAT table entries for a file.
  1382. ; Entry:    BP - Pointer to boot data structure.
  1383. ;           DI - Pointer to directory entry
  1384. ;-------------------------------------------------------------------------
  1385. clear_file    proc    near
  1386.         push    di
  1387.         push    si
  1388.         mov    bx,[di+1Ah]        ;Get starting cluster
  1389. clear_file_1:
  1390.         mov    di,bx            ;Save FAT pointer
  1391.         call    get_fat_entry
  1392.         pushf                ;Save end of file flag
  1393.         xchg    di,bx
  1394.         xor    ax,ax
  1395.         call    write_fat_entry        ;Zero entry to free cluster
  1396.         popf    
  1397.         jc    clear_file_1
  1398.         pop    si
  1399.         pop    di
  1400.         ret
  1401. clear_file    endp
  1402.  
  1403. ;-------------------------------------------------------------------------
  1404. ; WRITE FAT ENTRY - Writes FAT table entry 
  1405. ; Entry:    BP - Pointer to boot data structure.
  1406. ;           DI - Pointer to fat table entry
  1407. ;           AX - Data to write to FAT table
  1408. ;-------------------------------------------------------------------------
  1409. write_fat_entry    proc    near
  1410.         push    ax
  1411.         push    bx
  1412.         push    dx
  1413.         push    di
  1414.         push    ds
  1415.         push    es
  1416.  
  1417.         mov    ds,fat_seg_low         ;Load DS and ES with segments
  1418.         mov    es,fat_seg_high        ;  containing the FAT table.
  1419.  
  1420.         mov    dx,cs:fat_mask        ;Mask data to FAT size.
  1421.         or    dl,-1
  1422.         and    ax,dx
  1423.         xor    dx,dx        
  1424.         or     dx,cs:fat_mask        ;Mask unwanted bits
  1425.         jns    write_fat_4        ;If 0fffh, 12 bit FAT
  1426.             mov     bx,di                   ;16 bit FAT
  1427.         add    di,bx            ;Ptr = Index * 2
  1428.         jnc    write_fat_2        ;CF = 1, Upper segment
  1429. write_fat_1:
  1430.         mov    es:[di],ax        ;Write data
  1431.         jmp    short write_fat_3
  1432. write_fat_11:
  1433.         or    ax,bx
  1434. write_fat_2:
  1435.         mov    ds:[di],ax        ;Write data
  1436. write_fat_3:
  1437.         pop    es
  1438.         pop    ds
  1439.         pop    di
  1440.         pop    dx
  1441.         pop    bx
  1442.         pop    ax
  1443.         ret
  1444. write_fat_4:
  1445.         mov    bx,di
  1446.             shr     di,1                    ;12 bit FAT
  1447.         pushf
  1448.         add    di,bx
  1449.         mov    bx,ds:[di]        ;Get data
  1450.         popf
  1451.         jc    write_fat_5        ;Jump if odd
  1452.         and    bx,0f000h        ;Remove old data
  1453.         jmp    short write_fat_11
  1454. write_fat_5:
  1455.         and    bx,000fh        ;Remove old data
  1456.         push    cx
  1457.         mov    cl,4
  1458.         shl    ax,cl
  1459.         pop    cx
  1460.         jmp    short write_fat_11
  1461. write_fat_entry    endp
  1462.  
  1463. ;-----------------------------------------------------------------------
  1464. ; WRITE FAT TABLE - Writes data in memory FAT to disk FAT.
  1465. ; Entry: AX - FAT number to write
  1466. ;-----------------------------------------------------------------------
  1467. write_fat_table    proc    near
  1468.         push    ax
  1469.         push    cx
  1470.         push    es
  1471.         mov    cx,sec_per_fat        ;Compute starting sector
  1472.         mul    cx            ;  of this FAT
  1473.             add     ax,fat_sectorl          
  1474.             adc     dx,fat_sectorh
  1475.  
  1476.         push    ax
  1477.         push    dx
  1478.         mov    bx,FAT_SEGMENT1
  1479.         mov    es,bx
  1480.         xor    bx,bx
  1481.         mov    cx,low_fat_size
  1482.             call    write_disk        ;Write FAT 
  1483.         pop    dx
  1484.         pop    ax
  1485.             jc      write_fat_table_exit
  1486.  
  1487.         xor    cx,cx
  1488.         or     cx,hi_fat_size
  1489.         je    write_fat_table_exit
  1490.         add    ax,cx
  1491.         adc    dx,0
  1492.         mov    bx,FAT_SEGMENT2
  1493.         mov    es,bx
  1494.         xor    bx,bx
  1495.         call    write_disk
  1496. write_fat_table_exit:
  1497.         pop    es
  1498.         pop    cx
  1499.         pop    ax
  1500.         ret
  1501. write_fat_table    endp
  1502.  
  1503. ;-----------------------------------------------------------------------
  1504. ; RENAME FILE
  1505. ; Entry: SI - Ptr to file name to find
  1506. ;        DI - Ptr to new file name.
  1507. ;-----------------------------------------------------------------------
  1508. rename_file     proc    near
  1509.             push    di
  1510.         push    si
  1511.             cmp     byte ptr [di],0         ;See if filename exists
  1512.             je      rename_1
  1513.             push    di                      ;Save ptr to new file name
  1514.             call    find_file
  1515.             pop     si
  1516.             jc      rename_1
  1517.             mov     cx,11                   ;Copy name to entry.
  1518.             rep     movsb
  1519.             clc
  1520. rename_1:
  1521.             pop     di
  1522.         pop    si
  1523.             ret
  1524. rename_file     endp
  1525.  
  1526. ;-----------------------------------------------------------------------
  1527. ; MAKE OS NAMES
  1528. ; Entry: BL - Operating System number
  1529. ; Exit:  SI - Ptr array of 8.3 op sys names
  1530. ;-----------------------------------------------------------------------
  1531. make_os_names   proc    near
  1532.         push    bx
  1533.         mov    si,offset os_names_table
  1534.         add    bl,"0"
  1535.         mov    [si+7],bl
  1536.         mov    [si+18],bl
  1537.         mov    [si+29],bl
  1538.             pop     bx
  1539.             ret
  1540. make_os_names   endp
  1541.  
  1542. ;--------------------------------------------------------------------
  1543. ; WRITE VERT
  1544. ;--------------------------------------------------------------------
  1545. write_vert      proc    near
  1546.             lodsw                           ;Get location
  1547.             mov     dx,ax
  1548. write_vert1:
  1549.             mov     di,dx                   ;Save cursor pos
  1550.             call    set_cursor
  1551.             lodsb
  1552.             or      al,al
  1553.             je      write_vert2
  1554.             mov     ah,0ah                  ;BIOS Write Char
  1555.             mov     cx,1                    ;1 character
  1556.             call    vidint
  1557.             mov     dx,di                   ;Get cursor pos
  1558.             inc     dh
  1559.             call    set_cursor
  1560.             jmp     short write_vert1
  1561. write_vert2:
  1562.             ret
  1563. write_vert      endp
  1564.  
  1565. ;--------------------------------------------------------------------
  1566. ; WRITE LINENORM
  1567. ;Entry: SI - Offset of ASCIIZ string with leading word detailing
  1568. ;            row and column to start string.
  1569. ;--------------------------------------------------------------------
  1570. write_linenorm  proc    near
  1571.             push    dx
  1572.             lodsw                           ;Get location
  1573.             mov     dx,ax
  1574.             call    write_line_at
  1575.             pop     dx
  1576.             ret
  1577. write_linenorm  endp
  1578.  
  1579. ;--------------------------------------------------------------------
  1580. ; WRITE LINE AT/HI
  1581. ;Entry: DX - Row/Column to start string
  1582. ;       SI - Offset of ASCIIZ string
  1583. ;--------------------------------------------------------------------
  1584. write_line_hi   proc    near
  1585.             mov     bl,highlight_attr       ;Write with highlight attribute
  1586.             jmp     short write_line_at1
  1587. write_line_hi   endp
  1588.  
  1589. write_line_at   proc    near
  1590.             mov     bl,normal_attr
  1591. write_line_at1:
  1592.             call    set_cursor
  1593.             call    write_line
  1594.             ret
  1595. write_line_at   endp
  1596.  
  1597. ;--------------------------------------------------------------------
  1598. ; WRITE LINE
  1599. ;Entry: BL - Attribute for line
  1600. ;       SI - Offset of ASCIIZ string
  1601. ;--------------------------------------------------------------------
  1602. write_line      proc    near
  1603.             push    bx
  1604.             push    cx
  1605.             push    dx
  1606.             push    di
  1607.             xor     bh,bh                   ;Set video page
  1608.             mov     di,dx                   ;Save cursor pos
  1609. write_line_1:
  1610.             lodsb
  1611.             or      al,al
  1612.             je      write_line_2
  1613.             mov     ah,09h                  ;BIOS Write Char/Attr
  1614.             mov     cx,1                    ;1 character
  1615.             call    vidint
  1616.             inc     di
  1617.             mov     dx,di                   ;Get cursor pos
  1618.             call    set_cursor
  1619.             jmp     short write_line_1
  1620. write_line_2:
  1621.             pop     di
  1622.             pop     dx
  1623.             pop     cx
  1624.             pop     bx
  1625.             ret
  1626. write_line      endp
  1627.  
  1628. ;--------------------------------------------------------------------
  1629. ;WRITE BORDER
  1630. ;--------------------------------------------------------------------
  1631. write_border    proc    near
  1632.             call    set_cursor
  1633.             mov     ax,0acdh                ;Write border
  1634.             mov     cx,59
  1635.             call    vidint
  1636.             ret
  1637. write_border    endp
  1638.  
  1639. ;--------------------------------------------------------------------
  1640. ; WRITE BOX writes copyright box to the screen.
  1641. ;--------------------------------------------------------------------
  1642. write_box       proc near
  1643.             call    scroll_scr
  1644.         xor    bx,bx
  1645.         mov     bl,normal_attr
  1646.             mov     dx,010bh
  1647.             call    write_border
  1648.             mov     dx,050bh
  1649.             call    write_border
  1650.  
  1651.             mov     si,offset box1
  1652.             call    write_vert
  1653.             mov     si,offset box2
  1654.             call    write_vert
  1655.  
  1656.             mov     si,offset boxtext1      ;Point to 1st line
  1657.             mov     cx,3
  1658. title1:         mov     bl,normal_attr          ;Set attribute
  1659.             call    write_linenorm
  1660.             loop    title1
  1661.             ret
  1662. write_box       endp
  1663.  
  1664. ;-----------------------------------------------------------------------------
  1665. ; VIDINT - Calls the BIOS int 10h.  Saves BP to correct bug in old PC BIOS.
  1666. ;-----------------------------------------------------------------------------
  1667. vidint          proc near
  1668.             push    bp
  1669.             int     10h
  1670.             pop     bp
  1671.             ret
  1672. vidint          endp
  1673.  
  1674. ;-----------------------------------------------------------------------------
  1675. ; SCROLL SCR Clears the screen.
  1676. ;-----------------------------------------------------------------------------
  1677. scroll_scr      proc    near
  1678.             xor     cx,cx
  1679.         mov    dh,screen_rows
  1680.             mov     dl,50h
  1681.             call    scroll_block
  1682.             ret
  1683. scroll_scr      endp
  1684.  
  1685. ;-----------------------------------------------------------------------------
  1686. ; SCROLL HALF Clears the screen below the copyright box.
  1687. ;-----------------------------------------------------------------------------
  1688. scroll_half     proc    near
  1689.             mov     cx,0700h                ;Row 7 Col 0
  1690.             mov     dx,1950h
  1691.             call    scroll_block
  1692.             ret
  1693. scroll_half     endp
  1694.  
  1695. ;-----------------------------------------------------------------------------
  1696. ; SCROLL BLOCK Clears a part of the screen.
  1697. ; Entry: CX - Upper left corner
  1698. ;        DX - Lower right corner
  1699. ;-----------------------------------------------------------------------------
  1700. scroll_block    proc    near
  1701.             push    bx
  1702.             xor     bx,bx
  1703.             mov     bh,normal_attr
  1704.             mov     ax,0600h                ;Scroll up
  1705.             call    vidint
  1706.             pop     bx
  1707.             ret
  1708. scroll_block    endp
  1709.  
  1710. ;-----------------------------------------------------------------------------
  1711. ; SCROLL BLOCK Clears a part of the screen.
  1712. ; Entry: DX - Cursor Location
  1713. ;-----------------------------------------------------------------------------
  1714. set_cursor      proc    near
  1715.         push    ax
  1716.         push    bx
  1717.             mov     ah,02h                  ;Set cursor
  1718.             xor     bx,bx
  1719.             call    vidint
  1720.         pop    bx
  1721.         pop    ax
  1722.         ret
  1723. set_cursor      endp
  1724.  
  1725. ;-----------------------------------------------------------------------------
  1726. ; PRINTNUM - Prints a single digit number to the screen.
  1727. ; Entry:  AL - binary number
  1728. ;         DX - Cursor location
  1729. ;-----------------------------------------------------------------------------
  1730. printnum        proc    near
  1731.             add     al,30h
  1732.             mov     si,offset number_buff
  1733.             mov     [si],al
  1734.             call    write_line_at           ;Write number
  1735.             ret
  1736. printnum        endp
  1737.  
  1738. ;-----------------------------------------------------------------------------
  1739. ; HEX2ASC converts a binary number to ASCII and prints it to the screen.
  1740. ; Entry:  AX - binary number
  1741. ;-----------------------------------------------------------------------------
  1742. hex2asc         proc    near
  1743.             call    set_cursor
  1744.         xor    cx,cx
  1745.         mov    cl,1            ;If number = 0, print 1
  1746.         or    ax,ax            ;  zero.
  1747.         jne    hex_0
  1748.         mov    al,"0"
  1749.         jmp    short hex_1
  1750. hex_0:
  1751.             mov     cl,3                    ;Allow max of three digits
  1752. hex_loop1:
  1753.             xor     dx,dx                   ;Clear high word
  1754.             mov     bx,10                   ;Load number base
  1755.             div     bx                      ;Divide by base (10)
  1756.             add     dl,30h                  ;Convert to ascii
  1757.             push    dx                      ;Save digit on stack
  1758.             loop    hex_loop1
  1759.             mov     cx,3                    ;Allow max of three digits
  1760.             mov     bl,"0"                  ;Set leading zero indicator
  1761. hex_loop2:
  1762.             pop     ax                      ;Get digit off stack
  1763.             or      bl,al                   ;Don't print leading zeros.
  1764.             cmp     bl,"0"                  ;The first non zero will
  1765.             jne     hex_1                   ;  change bl to non-zero.
  1766.             mov     al,20h
  1767. hex_1:
  1768.             push    bx
  1769.             mov     ah,0eh                  ;Write TTY
  1770.             mov     bl,12h
  1771.             call    vidint
  1772.             pop     bx
  1773.             loop    hex_loop2
  1774. hex_exit:
  1775.             ret
  1776. hex2asc         endp
  1777. ;-----------------------------------------------------------------------------
  1778. ; Extended boot data.
  1779. ;-----------------------------------------------------------------------------
  1780. boot_data_start =       $
  1781. boot_array      =       $
  1782. name1           db      "DOS Session         ",0
  1783. auto1           db      "AUTOEXECMB1"
  1784. config1         db      "CONFIG  MB1"
  1785. ostype1         db      1                       ;Index into op sys table
  1786.  
  1787. name2           db      NAME_LENGTH dup (80h),0
  1788.             db      "AUTOEXECMB2"
  1789.             db      "CONFIG  MB2"
  1790.             db      0
  1791.  
  1792. name3           db      NAME_LENGTH dup (80h),0
  1793.             db      "AUTOEXECMB3"
  1794.             db      "CONFIG  MB3"
  1795.             db      0
  1796.  
  1797. name4           db      NAME_LENGTH dup (80h),0
  1798.             db      "AUTOEXECMB4"
  1799.             db      "CONFIG  MB4"
  1800.             db      0
  1801. boot_array_end    =    $
  1802.  
  1803. opsys_table     =       $
  1804. os_name1        db      8 dup (80h),0           ;Name of operating system
  1805. os_ioname       db      "IO      SYS"           ;IO.SYS file name
  1806. os_comname      db      "MSDOS   SYS"           ;MSDOS.SYS file name
  1807. os_boottype    dw    0
  1808. os_name2        db      8 dup (80h),0
  1809.             db      "OS2LDR     "
  1810.             db      "OS2KRNL    "
  1811.         dw    0
  1812. os_name3        db      8 dup (80h),0
  1813.             db      "BIOS    SYS"
  1814.             db      "DOS     SYS"
  1815.             dw    0
  1816. os_name4        db      8 dup (80h),0
  1817.             db      "BIOS    SYS"
  1818.             db      "DOS     SYS"
  1819.               dw    0
  1820. opsys_table_end =       $
  1821. boot_data_end   =       $
  1822.  
  1823. normal_attr     db      COLOR_NORM
  1824. highlight_attr  db      COLOR_HIGH
  1825. screen_rows    db    0
  1826. last_timeout    dw      0
  1827. timeout_value   dw      0
  1828. no_DOS_flag    db    1            ;0 = No DOS resident.
  1829.  
  1830. number_buff     db      0,".",0
  1831.  
  1832. read_os_error    db    2,7,"Error Reading new DOS files",0
  1833. write_os_error    db    2,7,"Error Writing new DOS files",0
  1834. no_room_error    db    2,7,"Not enough room for new DOS files",0
  1835. boot_extend_err db      2,7,"Write error, Last choice booted.",0
  1836. change_os_msg    db    2,7,"Changing DOS System files",0
  1837.  
  1838. boot_os_msg    db    2,11,"Operating System: "
  1839. boot_os_msg1    db    NAME_LENGTH+1 dup (0)
  1840. boot_sess_msg    db    2,9,"Booting Session: "
  1841. boot_sess_msg1    db    9 dup (0)
  1842.  
  1843. timeout_str     db      41,23,"Time until default:",0
  1844. timetext1       db      61,23,"Indefinite",0
  1845. prompt_text     db      "Choice [ ]",0
  1846.  
  1847. autoexec_name   db      "AUTOEXECBAT"           ;Filenames to rename.
  1848. config_name     db      "CONFIG  SYS"
  1849.  
  1850. ibmbio_name    db    "IBMBIO  COM"        ;IBM DOS system file names
  1851. ibmcom_name    db    "IBMDOS  COM"
  1852. iosys_name    db    "IO      SYS"        ;MS DOS system file names
  1853. msdos_name    db    "MSDOS   SYS"
  1854.  
  1855. os_names_table    db    "MBOOTOSaBOT"        ;This array is used to hold
  1856.                   db    "MBOOTOSaSYS"        ;  the generated names of the
  1857.                   db    "MBOOTOSaCOM"        ;  DOS system  files.
  1858. ;
  1859. ; Boot Menu structure
  1860. ;
  1861. boot_menu       =       $
  1862. menu_struc      db      4                       ;Number of choices
  1863. selected        db      0                       ;Selected Item
  1864. prompt_loc      db      30,20                   ;Location of "Choices" prompt
  1865. timeout         dw      0                       ;Timeout value
  1866.             db      40,23                   ;Col, Row of Timeout string
  1867. firstitem       db      24,9                    ;Column, Row of menu item
  1868.             dw      offset name1            ;Offset of menu text
  1869.             db      24,11
  1870.             dw      offset name2
  1871.             db      24,13
  1872.             dw      offset name3
  1873.             db      24,15
  1874.             dw      offset name4
  1875.  
  1876. boxtext1        db      27,02,"PC Magazine",39,"s MultiBoot 1.0",0
  1877. boxtext2        db      26,03,"(c) 1991 Ziff Communications",0
  1878. boxtext3        db      32,04,"Douglas Boling",0
  1879. box1            db      10,01,201,186,186,186,200,0   ;"╔","║","║","║","╚"
  1880. box2            db      69,01,187,186,186,186,188,0   ;"╗","║","║","║","╝"
  1881.  
  1882. ;============================================================================
  1883. ;============================================================================
  1884. ; Start of installation code and data.
  1885. ;============================================================================
  1886. ;============================================================================
  1887.             even
  1888. install_start   =       $
  1889. inst_text1      db      "Session Title          AUTOEXEC File    "
  1890.             db      "CONFIG File      System",0
  1891.  
  1892. main_menu       db      8,0                     ;Number of choices, Selected
  1893.             db      30,22                   ;Location of "Choices" prompt
  1894.             dw      0                       ;Timeout value
  1895.             db      0,0                     ;Col, Row of Timeout string
  1896.             db      13,17                   ;Column, Row of menu item
  1897.             dw      offset add_entry        ;Offset of menu text
  1898.             db      13,18
  1899.             dw      offset delete_entry
  1900.             db      13,19
  1901.             dw      offset set_default
  1902.             db      13,20
  1903.             dw      offset add_osentry
  1904.             db      40,17
  1905.                 dw      offset install
  1906.             db      40,18
  1907.                 dw      offset remove
  1908.             db      40,19
  1909.             dw      offset exit_prog
  1910.             db      40,20
  1911.             dw      offset quit_prog
  1912.  
  1913. confirm_msg    db    20,16,"Do you wish to discard changes?",0
  1914.  
  1915. yes_text        db      "Yes",0
  1916. no_text         db      "No",0
  1917. yesno_menu      db      2,1                     ;Number of choices, Selected
  1918.             db      25,22                   ;Location of "Choices" prompt
  1919.             dw      0                       ;Timeout value
  1920.             db      0,0                     ;Col, Row of Timeout string
  1921.             db      25,18                   ;Column, Row of menu item
  1922.             dw      offset yes_text         ;Offset of menu text
  1923.             db      25,20
  1924.             dw      offset no_text
  1925.  
  1926. add_entry       db      "Add Session",0
  1927. delete_entry    db      "Delete Session",0
  1928. set_default     db      "Set Defaults",0
  1929. add_osentry     db      "Load Operating System",0
  1930. install         db      "Install MultiBoot",0
  1931. remove          db      "Remove MultiBoot",0
  1932. exit_prog       db      "Update and Exit MultiBoot",0
  1933. quit_prog       db      "Quit MultiBoot",0
  1934.  
  1935. return_text     db      "Update and Return",0
  1936. quit_text       db      "Return Without Changing",0
  1937. unused_text     db      "< Unused >",0
  1938. unused_text_end =       $
  1939.  
  1940. os2knl_name    db    "OS2KRNL    "
  1941. os2ldr_name    db    "OS2LDR     "
  1942. os2boot_aname    db    "C:\OS2\SYSTEM\BOOT.OS2",0
  1943.  
  1944. default_str     db      "Def.",0
  1945.  
  1946. command_table   dw      offset main_menu        ;Offset of menu for this table
  1947.                 dw      offset main_add         ;Command jump table
  1948.             dw      offset main_delete
  1949.             dw      offset main_defaults
  1950.             dw      offset main_osadd
  1951.             dw      offset main_install
  1952.             dw      offset main_remove
  1953.             dw      offset exit
  1954.             dw      offset quit
  1955.  
  1956. dos_version     dw      0
  1957. installed_flag  db      0                       ;Set if MultiBoot installed
  1958. changed_flag    db      0
  1959. local_changed   db      0
  1960. huge_flag    db    0            ;Set if target disk > 32M 
  1961. targ_sec_per_cluster dw 0
  1962.  
  1963. session_count    db    0            ;Number of used sessions
  1964. opsys_count    db    0            ;Number of operating systems
  1965.  
  1966. iosys_size    dw    0            ;Size of IO.SYS read
  1967. doscom_size    dw    0            ;Size of MSDOS.SYS read
  1968. opsys_ostype     dw    0            ;DOS File config 
  1969.  
  1970. databuff_ptr    dd      0                       ;Pointer to data buffer
  1971. databuff1_ptr   dd      0                       ;Pointer to second data buffer
  1972. crit_vec        dd    0            ;Saved critical error vector
  1973. ctlc_vec        dd    0            ;Saved control C vector
  1974. ctlc_stack    dw    0
  1975. ctlc_return    dw    0
  1976.  
  1977. drive_letter    db      "A"                     ;Target drive
  1978.  
  1979. installed_data    =    $
  1980.         db    3 dup (0)        ;Bytes for jump instruction
  1981. inst_data_ptr    dw    0            ;Offset of last boot data
  1982. inst_data_size    dw    0            ;Size of last boot data
  1983. inst_sess_ptr    dw    0            ;Offset of boot session table 
  1984. inst_sess_size    dw    0            ;Size of boot session table
  1985. inst_boot_ptr    dw    0            ;Offset of boot os table 
  1986. inst_boot_size    dw    0            ;Size of boot os table
  1987. inst_version    dw    0            ;Version of installed code
  1988. installed_data_end =    $    
  1989.  
  1990. key_buffer      db      64 dup (0)
  1991. temp_buff       db      64 dup (0)
  1992. filename_buff    db    20 dup (0)
  1993. temp        dw    0            ;Temp storage buffer
  1994.  
  1995.  
  1996. errmsg0         db      "Requires at least DOS 2.x$"
  1997. errmsg1         db      "This program cannot be run under OS/2$"
  1998. errmsg2         db      "Not enough memory for MultiBoot$"
  1999. errmsg3         db      "Too many open files$"
  2000. errmsg4         db      "Access to files denied$"
  2001. errmsg5         db      "Drive Letter not specified on command line$"
  2002. errmsg6         db      "Drive Letter invalid$"
  2003. errmsg7         db      "MultiBoot file MBOOT.SYS not found$"
  2004. errmsg8        db    "Not a bootable disk or unknown operating system$"
  2005. errmsg9        db    "MultiBoot must be run in 80 column mode$"
  2006. errmsg10    db    "Installed data is incompatible with this version$"
  2007. crmsg           db      13,10,"$"
  2008.  
  2009. error_msg_loc   dw      180ah                   ;Column, Row of error msgs
  2010.  
  2011. errmsg20        db      "Install error",0
  2012. errmsg21        db      "MultiBoot Already Installed",0
  2013. errmsg22        db      "Remove error",0
  2014. errmsg23        db      "MultiBoot Not Installed",0
  2015.  
  2016. ;-----------------------------------------------------------------------------
  2017. ; Prevent Abort,Retry,Ignore error msg with this dummy crit. error routine
  2018. ;-----------------------------------------------------------------------------
  2019. crit_error      proc    far
  2020.             mov     al,0                    ;Ignore critical error.
  2021.             iret
  2022. crit_error      endp
  2023.  
  2024. ;-----------------------------------------------------------------------------
  2025. ; Installation code.
  2026. ;-----------------------------------------------------------------------------
  2027. main            proc    near
  2028.             assume  ds:code
  2029.             cld                             ;Set string operations up
  2030.             mov     ah,30h                  ;Get DOS version, run only
  2031.             int     21h                     ;  if 2.0 or greater.
  2032.             xchg    al,ah                   ;Swap major, minor numbers
  2033.             mov     dx,offset errmsg0       ;Bad DOS version
  2034.             cmp     ah,2
  2035.             jb      jmp1_error_exit
  2036.             mov     dx,offset errmsg1       ;Program cannot be run in the
  2037.             cmp     ah,10                   ;  DOS box under OS/2.
  2038.             jae     jmp1_error_exit
  2039.             mov     dos_version,ax          ;Save version number
  2040.  
  2041.             mov     sp,offset end_of_code + 512     ;Move stack
  2042.             mov     ah,4ah                          ;Reduce memory alloc
  2043.             mov     bx,offset end_of_code + 527
  2044.             mov     cl,4
  2045.             shr     bx,cl
  2046.             int     21h
  2047.  
  2048.         int    12h            ;Get size of machine RAM 
  2049.         cmp    ax,384            ;Must be at least 384K to
  2050.             mov     dx,offset errmsg2       ;  use extended boot code.
  2051.             jb      jmp1_error_exit
  2052.  
  2053.             mov     ah,48h                  ;Allocate memory block for
  2054.             mov     bx,1000h                ;  data buffer.
  2055.             int     21h
  2056.             mov     dx,offset errmsg2       ;Not enough memory msg
  2057.             jc      jmp1_error_exit
  2058.             mov     word ptr databuff_ptr[2],ax     ;Save segment.
  2059.  
  2060.             mov     ah,48h                  ;Allocate memory block for
  2061.             mov     bx,1000h                ;  second data buffer.
  2062.             int     21h
  2063.             mov     dx,offset errmsg2       ;Not enough memory msg
  2064.             jc      jmp1_error_exit
  2065.             mov     word ptr databuff1_ptr[2],ax     ;Save segment.
  2066.         
  2067.         call    set_ctlc_vec        ;Setup Control-C routine
  2068.  
  2069.             mov     si,81h                  ;Point to command line tail
  2070.             xor     cx,cx
  2071.             or      cl,[si-1]               ;Get cmd tail length
  2072.             jne     main_2
  2073. main_1:
  2074.             mov     dx,offset errmsg5       ;Drive letter not specified.
  2075. jmp1_error_exit:
  2076.             jmp     error_exit
  2077. main_2:
  2078.             lodsb
  2079.             cmp     al,13                   ;See if end of line
  2080.             je      main_1                  ;If so, error.
  2081.             cmp     al," "
  2082.             ja      main_3
  2083.             loop    main_2
  2084.             jmp     short main_1
  2085. main_3:
  2086.         cmp    byte ptr [si],":"    ;Make sure drive letter 
  2087.         jne    main_1            ;  terminated by colon.
  2088.             and     al,0dfh                 ;Convert drive letter to
  2089.             cmp     al,"A"            ;  upper case.
  2090.             jb      main_1
  2091.             cmp     al,"Z"
  2092.             ja      main_1
  2093.             mov     drive_letter,al         ;Save drive letter
  2094.  
  2095.         call    set_crit_vec        ;Set crit vec to int routine
  2096.         call    huge_disk_check        ;See if target disk > 32 Meg
  2097.         call    reset_crit_vec        
  2098.         mov    dx,offset errmsg6
  2099.         jc    jmp1_error_exit
  2100.         je    main_not_huge
  2101.         inc    huge_flag        ;If so, set flag
  2102. main_not_huge:    
  2103.         mov    targ_sec_per_cluster,di
  2104.             call    check_os                ;See what system on target
  2105.          cmp    al,-1            ;  disk.
  2106.             mov     dx,offset errmsg6    ;See if error reading disk.
  2107.             je      jmp1_error_exit
  2108.  
  2109.         push    ax
  2110.         xor    al,al            ;Copy BIOS parameter block
  2111.         call    copy_bpb        ;  to boot rec data area.
  2112.         pop    ax
  2113.  
  2114.         cmp    al,3               ;See if MultiBoot installed
  2115.         je    main_installed
  2116.         mov    dx,offset errmsg8    ;If OS unknown or unbootable,
  2117.         cmp    al,2            ;  error.
  2118.         jae    jmp1_error_exit
  2119.  
  2120.         call    setup_multiboot        ;Not installed, setup.
  2121.         jmp    short main_5
  2122. main_installed:
  2123.             inc     installed_flag          ;Set installed flag
  2124.         call    get_inst_data        ;Read data from MBOOT.SYS
  2125.         jc    jmp1_error_exit
  2126. main_5:
  2127.         mov    cx,4
  2128.         mov    si,offset opsys_table    ;Count sessions and op systems
  2129.         mov    di,offset boot_array
  2130.         add    di,OSTYPE_OFFSET
  2131. main_count_loop:
  2132.         cmp    byte ptr [si],80h    ;If lead byte 80h, entry
  2133.         jae    main_6             ;  unused.
  2134.         inc    opsys_count        ;Inc number of op systems
  2135. main_6:
  2136.         cmp    byte ptr [di],0        ;Op Sys = 0, no session.
  2137.         je    main_7
  2138.         inc    session_count
  2139. main_7:
  2140.         add    di,NEXT_ENTRY        ;Point to next entries
  2141.         add    si,NEXT_OSENTRY
  2142.         loop    main_count_loop
  2143.  
  2144.         push    ds
  2145.         mov    ax,40h            ;Get number of screen rows
  2146.         mov    ds,ax
  2147.         mov    dl,[84h]        
  2148.         pop    ds
  2149.         mov    screen_rows,dl
  2150.  
  2151.         mov    ah,0fh            ;Read video mode
  2152.         call    vidint
  2153.         mov    dx,offset errmsg9    ;Must be in 80 column mode
  2154.         cmp    ah,80
  2155.         jb    error_exit
  2156.         cmp    al,0fh            ;Check for BW modes
  2157.         je    main_set_bw
  2158.         cmp    al,6
  2159.         jb    main_set_color
  2160.         cmp    al,7
  2161.         ja    main_set_color
  2162. main_set_bw:
  2163.         mov    normal_attr,BW_NORM    ;Use Black/White attributes
  2164.         mov    highlight_attr,BW_HIGH
  2165. main_set_color:
  2166.             call    write_box               ;Write copyright box
  2167. main_loop:
  2168.             mov     di,offset name1        ;Display current sessions
  2169.             call    disp_settings
  2170.         mov    local_changed,0
  2171.         mov    si,offset command_table    ;Display menu and jump to 
  2172.         mov    al,1            ;  proper routine. Default
  2173.         call    jump_menu        ;  to Add Session.
  2174.             pushf
  2175.             cmp     al,-1                   ;See if exit
  2176.             je      main_exit
  2177.             add     changed_flag,al         ;Set flag if mboot modified.
  2178.             call    scroll_half
  2179.             popf
  2180.             jnc     main_loop               ;If carry, print message
  2181.  
  2182.             call    write_error             ;Print error message
  2183.             jmp     short main_loop
  2184. error_exit:
  2185.             mov     ah,9                    ;Print error message
  2186.             int     21h
  2187.             mov     dx,offset crmsg
  2188.             mov     ah,9                    ;Insert carrage return
  2189.             int     21h
  2190.             mov     al,1
  2191.             jmp     short main_exit1
  2192. main_exit:
  2193.             popf                            ;Remove flags from stack
  2194.         mov    dx,0700h        ;Set cursor to Row 7 Column 0.
  2195.         call    set_cursor
  2196.             xor     ax,ax                   ;Clear return code
  2197. main_exit1:
  2198.             push    ax
  2199.             mov     ax,word ptr databuff_ptr[2]  ;Get segment.
  2200.             or      ax,ax
  2201.             je      main_exit2
  2202.             mov     es,ax
  2203.             mov     ah,49h                  ;Free data buffer
  2204.             int     21h
  2205. main_exit2:
  2206.             mov     ax,word ptr databuff1_ptr[2]  ;Get segment.
  2207.             or      ax,ax
  2208.             je      main_exit3
  2209.             mov     es,ax
  2210.             mov     ah,49h                  ;Free data buffer
  2211.             int     21h
  2212. main_exit3:
  2213.             pop     ax
  2214.             mov     ah,4ch
  2215.             int     21h
  2216. main            endp
  2217.  
  2218. ;--------------------------------------------------------------------
  2219. ; SETUP MULTIBOOT - Configures Multiboot if not installed.
  2220. ; Entry: AX - Operating system on target disk
  2221. ;        BX - DOS version
  2222. ;        CX - Consecutive clusters used by DOS files
  2223. ;--------------------------------------------------------------------
  2224. setup_multiboot    proc    near
  2225.         push    ax            ;Save operating system type
  2226.         push    bx            ;  and size.
  2227.         mov    opsys_clusters,cx
  2228.  
  2229.         mov    ah,2ch            ;Get system time for time
  2230.         int    21h            ;  stamp ID
  2231.         mov    word ptr time_stamp,cx
  2232.         mov    word ptr time_stamp[2],dx
  2233.         pop    cx            ;Get os config
  2234.         pop    ax            ;Get os type
  2235.  
  2236.             mov     bl,1                  ;The current os becomes the 
  2237.         call    copy_os_name        ;  default.
  2238.  
  2239.         mov    si,offset boot_extend_start  ;Copy installed data ptrs
  2240.         mov    di,offset installed_data
  2241.         mov    cx,offset installed_data_end - offset installed_data
  2242.         rep    movsb
  2243.  
  2244.         cmp    ah,1            ;See if OS/2 installed
  2245.         jne    setup_multiboot_1
  2246.         mov    dx,offset os2boot_aname    ;Yes, look for BOOT.OS2
  2247.         mov    cl,drive_letter
  2248.         mov    byte ptr os2boot_aname,cl
  2249.         push    es
  2250.         les    si,databuff_ptr        ;Read OS/2 boot record file.
  2251.         call    read_file        
  2252.         pop    es
  2253.         jc    setup_multiboot_1
  2254.         mov    bl,2
  2255.         mov    cx,100h            ;OS type = OS/2
  2256.         call    copy_os_name        ;Copy OEM name.
  2257. setup_multiboot_1:
  2258.         mov    bl,1            ;Verify default session
  2259.         call    get_entry        ;  filenames are not used.
  2260.         mov    cx,8
  2261. setup_multiboot_2:
  2262.         lea    si,[bx+AUTO_OFFSET]    ;Search for the filenames used
  2263.         call    find_first        ;  in the default session.  If
  2264.         jnc    setup_multiboot_3    ;  used, rename by changing 
  2265.         lea    si,[bx+CONFIG_OFFSET]    ;  the extension.
  2266.         call    find_first
  2267.         jc    setup_exit
  2268. setup_multiboot_3:
  2269.         inc    byte ptr [bx+AUTO_OFFSET+10]
  2270.         inc    byte ptr [bx+CONFIG_OFFSET+10]
  2271.         loop    setup_multiboot_2        ;If all filenames used
  2272.         mov    byte ptr [bx+OSTYPE_OFFSET],0    ;  delete default.
  2273. setup_exit:
  2274.         ret
  2275. setup_multiboot    endp
  2276.  
  2277. ;--------------------------------------------------------------------
  2278. ; GET INST DATA - Reads the configutation data from MBOOT.SYS
  2279. ; Exit:  CF - Set if error
  2280. ;        DX - Offset of error message.
  2281. ;--------------------------------------------------------------------
  2282. get_inst_data    proc    near
  2283.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  2284.             call    make_filename           ;  read the boot information.
  2285.         xor    cx,cx
  2286.         call    set_attributes        ;Clear the file attributes.
  2287.             mov     ax,3d02h
  2288.             int     21h
  2289.         jc    get_inst_file_error
  2290.  
  2291.         mov    bx,ax            ;Copy file handle
  2292.         mov    ah,3fh            ;Read ptr to boot table
  2293.         mov    dx,offset installed_data
  2294.         mov    cx,offset installed_data_end - offset installed_data
  2295.         int    21h
  2296.         jc    get_inst_file_error
  2297.  
  2298.         mov    dx,offset errmsg10    ;See if installed data    
  2299.         cmp    inst_version,20h    ;  compatible    
  2300.         jae    get_inst_data_error
  2301.  
  2302.         mov    ax,4200h        ;Move file ptr 
  2303.         mov    dx,inst_data_ptr    
  2304.         xor    cx,cx
  2305.         int    21h
  2306.         jc    get_inst_file_error
  2307.             mov     ah,3fh                  ;Read default session data
  2308.             mov     dx,offset boot_data1
  2309.             mov     cx,inst_data_size
  2310.             int     21h
  2311.             jnc     get_inst_data_1
  2312. get_inst_file_error:
  2313.             mov     dx,offset errmsg7       ;Boot file error.
  2314.             cmp     ax,2                    ;See if file not found
  2315.             je      get_inst_data_error     ;Yes, error
  2316.             mov     dx,offset errmsg3       ;See if too many files opened
  2317.             cmp     ax,4
  2318.             je      get_inst_data_error
  2319.             mov     dx,offset errmsg4       ;Assume access denied
  2320. get_inst_data_error:
  2321.         stc
  2322.             jmp     short get_inst_data_exit
  2323. get_inst_data_1:
  2324.         mov    ax,4200h        ;Move file ptr to session table
  2325.         mov    dx,inst_sess_ptr    
  2326.         xor    cx,cx
  2327.         int    21h
  2328.         jc    get_inst_file_error
  2329.             mov     ah,3fh                  ;Read boot session data 
  2330.             mov     dx,offset boot_array
  2331.             mov     cx,inst_sess_size
  2332.             int     21h
  2333.         jc    get_inst_file_error
  2334.  
  2335.         mov    ax,4200h        ;Move file ptr to session table
  2336.         mov    dx,inst_boot_ptr    
  2337.         xor    cx,cx
  2338.         int    21h
  2339.         jc    get_inst_file_error
  2340.             mov     ah,3fh                  ;Read boot session data 
  2341.             mov     dx,offset opsys_table
  2342.             mov     cx,inst_boot_size
  2343.             int     21h
  2344.         jc    get_inst_file_error
  2345.  
  2346.             mov     ah,3eh                  ;Close file
  2347.             int     21h
  2348.             mov     si,offset mboot_name    ;Set MBOOT.SYS file attributes
  2349.             call    make_filename           ;  to hidden, system, and  
  2350.         mov    cx,SYSFILE_ATTR        ;  read only.
  2351.         call    set_attributes        
  2352.         jc    get_inst_file_error
  2353. get_inst_data_exit:
  2354.         ret
  2355. get_inst_data    endp
  2356.  
  2357. ;--------------------------------------------------------------------
  2358. ; MAIN ADD - Displays the Add Session submenu.
  2359. ;--------------------------------------------------------------------
  2360. local_add1      db      NEXT_ENTRY dup (0)      ;Local copy of boot table
  2361. local_add2      db      NEXT_ENTRY dup (0)
  2362. local_add3      db      NEXT_ENTRY dup (0)
  2363. local_add4      db      NEXT_ENTRY dup (0)
  2364. local_add_end   =       $
  2365. local_add_count    db    0
  2366.  
  2367. local_selection dw      0                       ;Current selected session
  2368. local_add_menu  =       $
  2369.             db      4                       ;Number of choices
  2370. add_select      db      0                       ;Selected Item
  2371.             db      30,20                   ;Location of "Choices" prompt
  2372.             dw      0                       ;Timeout value
  2373.             db      0, 0                    ;Col, Row of Timeout string
  2374.             db      24,9                    ;Column, Row of menu item
  2375.             dw      offset local_add1       ;Offset of menu text
  2376.             db      24,11
  2377.             dw      offset local_add2
  2378.             db      24,13
  2379.             dw      offset local_add3
  2380.             db      24,15
  2381.             dw      offset local_add4
  2382.  
  2383. add_str2        db      20,7
  2384. add_select_str1 db      "Current Sessions",0
  2385. add_add_text    db      "Add Session",0
  2386. add_rename_text db      "Rename Session",0
  2387.  
  2388. add_str4        db      05,14,"Enter the title of the session:",0
  2389. add_str7        db      15,16,"Is this correct?",0
  2390.  
  2391. add_str_msg1    db      10,22,"Press Ctrl-Break to return to Add Menu",0
  2392. add_str_err1    db      "No Sessions Added",0
  2393. add_str_err2    db      "No free sessions, delete a session first",0
  2394.  
  2395. add_table    dw    offset add_menu
  2396.         dw    offset add_add_sess
  2397.         dw    offset add_rename
  2398.         dw    offset add_exit
  2399.         dw    offset add_quit
  2400.  
  2401. add_menu        db      4,0                     ;Number of choices, Selected
  2402.             db      30,22                   ;Location of "Choices" prompt
  2403.             dw      0                       ;Timeout value
  2404.             db      0,0                     ;Col, Row of Timeout string
  2405.             db      25,17                   ;Column, Row of menu item
  2406.             dw      offset add_add_text     ;Offset of menu text
  2407.             db      25,18
  2408.             dw      offset add_rename_text 
  2409.             db      25,19
  2410.             dw      offset return_text
  2411.             db      25,20
  2412.             dw      offset quit_text
  2413.  
  2414. main_add        proc    near
  2415.             assume  cs:code,ds:code
  2416.             mov     di,offset local_add1    ;Copy boot array
  2417.             mov     si,offset boot_array
  2418.             mov     cx,4                    ;4 Entries.
  2419. main_add_0:
  2420.              push    cx                      ;Copy the contents of the
  2421.              mov     cx,NEXT_ENTRY           ;  marked unused, replace
  2422.         mov    bx,di
  2423.              rep     movsb                   
  2424.              cmp     byte ptr [bx+OSTYPE_OFFSET],0 ;See if session unused.
  2425.              jne     main_add_02
  2426.              mov     byte ptr [bx+AUTO_OFFSET],0     ;If unused, clear
  2427.              mov     byte ptr [bx+CONFIG_OFFSET],0   ;  filename entries
  2428.         mov    byte ptr [bx],80h
  2429. main_add_02:
  2430.              pop     cx
  2431.              loop    main_add_0
  2432.         mov    al,session_count    ;Copy session count
  2433.         mov    local_add_count,al
  2434. main_add_1:
  2435.             mov     di,offset local_add1    ;Display current sessions.
  2436.             call    disp_settings
  2437.  
  2438.             mov     si,offset add_table    ;Display the add menu
  2439.             mov     al,1
  2440.             call    jump_menu        ;Call submenu routines
  2441.         pushf                ;Save carry flag
  2442.         pop    bx
  2443.         cmp    al,-1
  2444.         jne    main_add_1
  2445.             mov     al,local_changed        ;Indicate if changes made.
  2446.         push    bx            ;Restore carry flag if needed
  2447.         popf
  2448.         ret
  2449.  
  2450. ;--------------------------------------------------------------------
  2451. ; ADD ADD SESSION - adds an entry to the boot table.
  2452. ;--------------------------------------------------------------------
  2453. add_add_sess    proc    near
  2454.             call    scroll_half             
  2455.         xor    bx,bx
  2456.         mov    bl,local_add_count      ;Get number of sessions.
  2457.         cmp    bl,4            ;See if too many
  2458.         jb    add_add_sess_1
  2459.         mov    si,offset add_str_err2
  2460.         call    write_error        ;Print error message
  2461.         jmp    add_add_sess_exit
  2462. add_add_sess_1:
  2463.         mov    cx,4
  2464.         xor    bx,bx            ;Find first free boot table        
  2465.         mov    si,offset local_add1    ;  entry.
  2466. add_add_sess_11:
  2467.         inc    bx
  2468.         cmp    byte ptr [si+OSTYPE_OFFSET],0
  2469.         je    add_add_sess_12        
  2470.         add    si,NEXT_ENTRY
  2471.         loop    add_add_sess_11
  2472. add_add_sess_12:
  2473.         call    get_sess_name        ;Get session name
  2474.         jnc    add_add_sess_13
  2475. jmp_add_add_sess_5:
  2476.         jmp    add_add_sess_5
  2477. add_add_sess_13:
  2478.         mov    local_selection,bp
  2479.             mov     si,offset autoexec_name ;Point to AUTOEXEC.BAT name
  2480.             call    add_file
  2481.         jc    jmp_add_add_sess_5
  2482.             mov     di,local_selection      ;Copy AUTOEXEC filename to
  2483.             add     di,AUTO_OFFSET          ;  local array.
  2484.             mov     cx,12
  2485.             rep     movsb
  2486.  
  2487.             mov     si,offset config_name   ;Point to CONFIG.SYS name
  2488.             call    add_file
  2489.         jc    add_add_sess_5
  2490.             mov     di,local_selection      ;Copy CONFIG filename to
  2491.             add     di,CONFIG_OFFSET        ;  local array.
  2492.             mov     cx,12
  2493.             rep     movsb
  2494.  
  2495.             mov     dh,10
  2496.             call    clear_line
  2497.             mov     di,local_selection      ;Write session data to screen
  2498.             call    disp_session
  2499.  
  2500.             mov     dh,14
  2501.             call    clear_line
  2502. add_add_sess_2:
  2503.         mov    bl,1            ;Assume only one OS.
  2504.         cmp    opsys_count,1
  2505.         je    add_add_sess_3         ;If only one OS, don't display
  2506.         call    get_ostype         ;  OS menu.
  2507.         or    bl,bl
  2508.         je    add_add_sess_2        ;Must select an os.
  2509. add_add_sess_3:
  2510.             mov     di,local_selection      ;Set OS type
  2511.             add     di,OSTYPE_OFFSET
  2512.             mov     byte ptr [di],bl
  2513.  
  2514.             mov     dh,10
  2515.             call    clear_line
  2516.             mov     di,local_selection      ;Write session data to screen
  2517.             call    disp_session
  2518.  
  2519.             mov     al,1
  2520.             mov     si,offset add_str7      ;Ask user to verify changes.
  2521.             call    msg_box
  2522.             cmp     bl,1                    ;See if Yes.
  2523.             je      add_add_sess_4
  2524.         mov    di,local_selection        ;If no, clear entries
  2525.         mov    byte ptr [di],80h        ;  and return to 
  2526.                mov     byte ptr [di+AUTO_OFFSET],0     ;  add menu.
  2527.              mov     byte ptr [di+CONFIG_OFFSET],0   
  2528.              mov     byte ptr [di+OSTYPE_OFFSET],0   
  2529.             jmp     short add_add_sess_exit
  2530. add_add_sess_4:
  2531.             mov     local_changed,1         ;Set changes flag
  2532.         inc    local_add_count      ;Inc number of sessions
  2533. add_add_sess_5:
  2534.             call    scroll_half
  2535. add_add_sess_exit:
  2536.         xor    al,al            
  2537.             ret
  2538. add_add_sess    endp
  2539.  
  2540. ;--------------------------------------------------------------------
  2541. ; ADD RENAME SESSION - Renames a session.
  2542. ;--------------------------------------------------------------------
  2543. add_rename    proc    near
  2544.         mov    bp,offset local_add_menu
  2545.         xor    ax,ax
  2546.         call    get_session_2        ;Ask for a session 
  2547.             jc      add_rename_session_exit
  2548.  
  2549.             or      bx,bx            ;See if no choice
  2550.             jz      add_rename_session_exit
  2551.  
  2552.         call    get_sess_name        ;Ask for a session name
  2553.         jc    add_rename_session_exit
  2554.         mov    local_changed,1
  2555. add_rename_session_exit:
  2556.             call    scroll_half
  2557.         xor    al,al            ;Clear exit flag
  2558.             ret
  2559. add_rename    endp
  2560. ;--------------------------------------------------------------------
  2561. ; ADD EXIT - Copies the local data to the main boot table then sets
  2562. ;             the exit flag
  2563. ;--------------------------------------------------------------------
  2564. add_exit    proc    near
  2565.             mov     bx,offset local_add1
  2566.             mov     dx,offset boot_array
  2567.             mov     cx,4                    ;4 Entries.
  2568. main_add_5:
  2569.             push    cx                      ;Copy only entrys used.
  2570.             mov     si,bx
  2571.             mov     di,dx
  2572.             cmp     byte ptr [bx+OSTYPE_OFFSET],0   ;See of entry used.
  2573.             je      main_add_6
  2574.             mov     cx,NEXT_ENTRY
  2575.             rep     movsb
  2576. main_add_6:
  2577.             add     dx,NEXT_ENTRY
  2578.             add     bx,NEXT_ENTRY
  2579.             pop     cx
  2580.             loop    main_add_5
  2581.         mov    al,local_add_count    ;Copy new number of sessions
  2582.         mov    session_count,al
  2583.             mov    al,-1            ;Set exit flag
  2584.         ret
  2585. add_exit    endp
  2586.     
  2587. ;--------------------------------------------------------------------
  2588. ; ADD QUIT - Querys user for verification then returns exit flag
  2589. ;--------------------------------------------------------------------
  2590. add_quit    proc    near    
  2591.         xor    al,al
  2592.             cmp     local_changed,0        ;See if any changes made
  2593.             je      add_quit_1
  2594.             call    confirm_quit
  2595.         jne    add_quit_exit
  2596.             mov     si,offset add_str_err1  ;No changes message.
  2597.             mov     local_changed,0         ;Clear changes flag
  2598. add_quit_1:
  2599.         mov    al,-1            ;Set exit flag
  2600. add_quit_exit:
  2601.         ret
  2602. add_quit    endp    
  2603. main_add        endp
  2604.  
  2605. ;--------------------------------------------------------------------
  2606. ; MAIN DELETE - Deletes an entry to the boot table.
  2607. ;--------------------------------------------------------------------
  2608. local_delete    dw      4 dup (0)               ;Delete flag for each session
  2609.  
  2610. delete_str2     db      20,07
  2611. del_select      db      "Select Session to Delete",0
  2612. delete_str3     db      15,11,"Do you want to delete the CONFIG.SYS"
  2613.             db      " and AUTOEXEC.BAT",0
  2614. delete_str4     db      15,12,"files for this Session?",0
  2615.  
  2616. delete_err1    db    "Can",39,"t delete active session.",0
  2617.  
  2618. tbdel_text      db      "To Be Deleted ->",0
  2619.  
  2620. delete_table    dw    offset delete_menu
  2621.         dw    offset delete_delete_session
  2622.         dw    offset delete_exit
  2623.         dw    offset add_quit
  2624.  
  2625. delete_menu     db      3,0                     ;Number of choices, Selected
  2626.             db      30,22                   ;Location of "Choices" prompt
  2627.             dw      0                       ;Timeout value
  2628.             db      0,0                     ;Col, Row of Timeout string
  2629.             db      25,18                   ;Column, Row of menu item
  2630.             dw      offset del_select       ;Offset of menu text
  2631.             db      25,19
  2632.             dw      offset return_text
  2633.             db      25,20
  2634.             dw      offset quit_text
  2635.  
  2636. main_delete     proc    near
  2637.             assume  cs:code,ds:code
  2638.             xor     ax,ax                   ;Clear local delete flags.
  2639.             mov     di,offset local_delete
  2640.             stosw
  2641.             stosw
  2642.             stosw
  2643.             stosw
  2644.         xor    bx,bx
  2645. main_delete_1:    
  2646.         push    bx
  2647.         popf
  2648.         jnc    main_delete_2
  2649.         call    write_error
  2650. main_delete_2:    
  2651.             mov     bp,offset boot_menu    ;Display sessions
  2652.         call    write_menu        ;  in menu form.
  2653.             mov     cx,4
  2654.             mov     dx,word ptr firstitem   ;Starting cursor loc from
  2655.             mov     dl,5                    ;  boot menu structure.
  2656.             mov     si,offset local_delete
  2657. main_delete_3:
  2658.             lodsw
  2659.             or      al,al                   ;See if session to be deleted
  2660.             je      main_delete_4           ;No, skip
  2661.             push    si
  2662.             mov     si,offset tbdel_text
  2663.             call    write_line_at
  2664.             pop     si
  2665. main_delete_4:
  2666.             inc     dh                      ;Move to next cursor location
  2667.             inc     dh
  2668.             loop    main_delete_3
  2669. ;Display delete menu.
  2670.             mov     si,offset delete_table    ;Display the delete menu
  2671.             mov     al,1
  2672.             call    jump_menu
  2673.         pushf                ;Save carry flag
  2674.         pop    bx
  2675.         cmp    al,-1            ;See if exit flag set
  2676.         jne    main_delete_1
  2677.             mov     al,local_changed        ;Indicate if changes made.
  2678.         push    bx            ;Restore carry flag if needed
  2679.         popf
  2680.         ret        
  2681.  
  2682. ;--------------------------------------------------------------------
  2683. ; DELETE DELETE SESSION - Querys the user for the session to delete 
  2684. ;--------------------------------------------------------------------
  2685. delete_delete_session    proc    near
  2686.             mov     al,0                    ;Get session to delete.
  2687.             call    get_session
  2688.             jc      delete_delete_exit
  2689.         cmp    bx,last_choice        ;Make sure not deleting 
  2690.         jne    delete_delete_0        ;  current session.
  2691.         mov    si,offset delete_err1
  2692.         xor    al,al
  2693.         stc    
  2694.         jmp    short delete_delete_exit1
  2695. delete_delete_0:
  2696.             push    bx
  2697.             call    scroll_half             ;See if we need to delete the
  2698.             mov     si,offset delete_str3   ;  CONFIG.SYS and AUTOEXEC.BAT
  2699.             call    write_linenorm          ;  files.
  2700.             mov     si,offset delete_str4
  2701.             mov     al,2
  2702.             call    msg_box
  2703.             mov     ah,bl                   ;Copy yes no answer
  2704.             pop     bx                      ;Restore selection to delete
  2705.             jnc     delete_delete_1
  2706.             mov     ah,2                    ;If <esc> force No reply.
  2707. delete_delete_1:
  2708.             dec     ah
  2709.             dec     bx
  2710.             shl     bx,1
  2711.             mov     al,1
  2712.             mov     [bx+local_delete],ax    ;Save delete flags for this
  2713.             call    scroll_half             ;  selection.
  2714. delete_delete_exit:
  2715.         xor    al,al            ;Clear exit flag
  2716. delete_delete_exit1:
  2717.         ret
  2718. delete_delete_session     endp
  2719.  
  2720. ;--------------------------------------------------------------------
  2721. ; DELETE EXIT - Performs the delete of sessions requested then sets
  2722. ;               the error flag.
  2723. ;--------------------------------------------------------------------
  2724. delete_exit    proc    near
  2725.             mov     cx,4
  2726.             mov     si,offset local_delete  ;Set ptr to delete selections
  2727.             mov     di,offset name1         ;Point to 1st session title
  2728. delete_exit_1:
  2729.             lodsw                           ;Get flag for selection
  2730.             or      al,al                   ;Delete entry?
  2731.             je      delete_exit_3
  2732.             mov     byte ptr [di+OSTYPE_OFFSET],0 ;Delete entry in list
  2733.             or      byte ptr [di],80h
  2734.         dec    session_count
  2735.             mov     local_changed,1         ;Set changed flag
  2736.             mov     dl,5
  2737.             sub     dl,cl
  2738.             cmp     dl,boot_default         ;If entry just deleted was
  2739.             jne     delete_exit_2           ;  the default, remove default.
  2740.             mov     boot_default,0
  2741. delete_exit_2:
  2742.             or      ah,ah                   ;Should the AUTOEXEC and
  2743.             jne     delete_exit_3           ;  CONFIG files be deleted?
  2744.             push    si
  2745.             lea     si,[di+AUTO_OFFSET]     ;Yes, delete files
  2746.             call    delete_file
  2747.             lea     si,[di+CONFIG_OFFSET]
  2748.             call    delete_file
  2749.             pop     si
  2750. delete_exit_3:
  2751.             add     di,NEXT_ENTRY           ;Point to next session title
  2752.             loop    delete_exit_1
  2753.         mov    al,-1            ;Set exit flag
  2754.         ret
  2755. delete_exit    endp
  2756. main_delete     endp
  2757.  
  2758. ;--------------------------------------------------------------------
  2759. ; INST OSADD - Adds an operating system to the disk.
  2760. ;--------------------------------------------------------------------
  2761. osadd_str0      db      25,07,"Current Operating Systems",0
  2762. osadd_str1      db      10,08,"Insert Diskette with new DOS system"
  2763.             db      " into Drive A:",0
  2764. osadd_str2      db      10,10,"Press any key when Diskette inserted.",0
  2765. osadd_str3      db      10,08,"Insert Target diskette into Drive A:",0
  2766. osadd_str4      db      10,08,"Current Operating System name: "
  2767. osadd_namestr    db    9 dup (0)
  2768. osadd_str5      db      10,10,"New Operating System name:",0
  2769. osadd_str6      db      10,10,"Reading DOS System files",0
  2770. osadd_str7      db      10,10,"Writing DOS System files",0
  2771. osadd_dos5    db    15,16,"Are you installing DOS 5.0 or greater?",0
  2772. osadd_dos4    db    15,16,"Are you installing DOS 4.0 or greater?",0
  2773. osadd_dos3    db    15,16,"Are you installing DOS 3.0 or greater?",0
  2774.  
  2775. osadd_err1    db    "Only four operating systems can be added",0
  2776. osadd_err2    db    "Can",39,"t delete last operating system",0
  2777. osadd_err3    db    "Diskette is not a bootable DOS diskette",0
  2778. osadd_err4    db    "MultiBoot installed on diskette",0
  2779. osadd_err5    db    "OS/2 cannot be installed from diskette",0
  2780. osadd_err6    db    "Error writing DOS System files to the disk",0
  2781. osadd_err7    db    "Operating system used by a session. Delete session "
  2782.         db    "first",0
  2783. osadd_err8    db    "New DOS system files larger than original DOS system"
  2784.         db    " files",0
  2785. osadd_err9    db    "Target disk not original MultiBoot disk."
  2786.         db    "  DOS system not loaded",0
  2787. osadd_err10    db    "MultiBoot must be installed before adding"
  2788.         db    " an Operating System",0
  2789. osadd_err11    db    "Error updating MBOOT.SYS file",0
  2790.  
  2791. osa_addos_text    db    "Add an operating system",0
  2792. osa_delos_text    db    "Delete an operating system",0
  2793. osa_renos_text    db    "Rename an operating system",0
  2794.  
  2795. osadd_table    dw    offset osadd_menu
  2796.         dw    offset osadd_add_opsys
  2797.         dw    offset osadd_del_opsys
  2798.         dw    offset osadd_ren_opsys
  2799.         dw    offset osadd_exit
  2800.  
  2801. osadd_menu      db      4,0                     ;Number of choices, Selected
  2802.             db      30,22                   ;Location of "Choices" prompt
  2803.             dw      0                       ;Timeout value
  2804.             db      0,0                     ;Col, Row of Timeout string
  2805.             db      25,17                   ;Column, Row of menu item
  2806.             dw      offset osa_addos_text   ;Offset of menu text
  2807.             db      25,18
  2808.             dw      offset osa_delos_text
  2809.             db      25,19
  2810.             dw      offset osa_renos_text
  2811.             db      25,20
  2812.             dw      offset return_text
  2813.  
  2814. main_osadd      proc    near
  2815.             assume  cs:code,ds:code
  2816.         xor    bx,bx            ;First time, no error.
  2817. main_osadd_1:    
  2818.         push    bx            ;Check for carry indicating
  2819.         popf                ;  an error message display
  2820.         jc    main_osadd_2
  2821.         call    scroll_half        ;Clear screen
  2822. main_osadd_2:
  2823.             mov     si,offset osadd_str0    ;Display current op systems
  2824.             call    write_linenorm        
  2825.  
  2826.         xor    cx,cx
  2827.         mov    cl,opsys_count        ;Four operating systems
  2828.         mov    dx,0920h        
  2829.         mov    si,offset opsys_table    ;Point to the opsys table
  2830. main_osadd_3:    
  2831.         push    si            
  2832.         call    write_line_at        
  2833.         pop    si
  2834.         add    si,NEXT_OSENTRY
  2835.         add    dh,2
  2836.         loop    main_osadd_3
  2837. ;Display os add menu.
  2838.             mov     si,offset osadd_table    ;Display the op sys add menu
  2839.             mov     al,1
  2840.             call    jump_menu
  2841.         pushf                ;Save carry flag
  2842.         pop    bx
  2843.         cmp    al,-1            ;See if exit flag set
  2844.         jne    main_osadd_1
  2845.             xor     ax,ax            ;Indicate if changes made.
  2846.         push    bx            ;Restore carry flag if needed
  2847.         popf
  2848.         ret        
  2849.  
  2850. ;--------------------------------------------------------------------
  2851. ; OSADD ADD OPSYS - Adds an operating system to the disk.
  2852. ;--------------------------------------------------------------------
  2853. osadd_add_opsys proc    near
  2854.         mov    si,offset osadd_err1    ;Only room for four operating
  2855.         cmp    opsys_count,4        ;  systems.
  2856.         jae    jmp_osadd_error
  2857.  
  2858.         mov    si,offset osadd_err10    ;Must be installed message
  2859.         cmp    installed_flag,0    
  2860.         je    jmp_osadd_error
  2861.  
  2862.             mov     si,offset osadd_str1    ;Prompt user for opsys 
  2863.             call    write_linenorm        ;  diskette.
  2864.             mov     si,offset osadd_str2
  2865.             call    write_linenorm
  2866.  
  2867.         call    fetch_key        ;Read a key from the keyboard
  2868.  
  2869.         call    clear_msg         ;Clear message off screen
  2870.             mov     si,offset osadd_str6    ;Reading files message
  2871.             call    write_linenorm
  2872.         
  2873.         mov    al,"A"            ;Set disk A
  2874.         call    get_opsys         ;Read operating sys from disk
  2875.  
  2876.         mov    ah,0             ;Ignore OS/2 flag
  2877.         push    ax            ;Save os type
  2878.         push    cx
  2879.         push    dx
  2880.         pushf                ;Save error flag
  2881.         cmp    drive_letter,"A"    
  2882.         jne    osadd_add_3
  2883.             mov     si,offset osadd_str3    ;Prompt user for target
  2884.             call    write_linenorm        ;  diskette.
  2885.             mov     si,offset osadd_str2
  2886.             call    write_linenorm
  2887.  
  2888.         call    fetch_key        ;Read a key from the keyboard
  2889. osadd_add_3:
  2890.         call    clear_msg         ;Clear message off screen
  2891.         popf                ;Restore error flags
  2892.         pop    dx            ;Restore IO.SYS size
  2893.         pop    cx            ;Restore DOS system size
  2894.         pop    ax            ;Restore os type
  2895.     
  2896.         jnc    osadd_add_11
  2897.         mov    si,offset osadd_err8
  2898.         cmp    al,7            ;See if Op sys too big
  2899.         je    jmp_osadd_error
  2900.         mov    si,offset osadd_err4
  2901.         cmp    al,3            ;See if Multiboot diskette 
  2902.         je     jmp_osadd_error
  2903.         mov    si,offset osadd_err5
  2904.         cmp    al,2            ;See if OS/2 diskette
  2905.         je    jmp_osadd_error
  2906.         mov    si,offset osadd_err3
  2907.         cmp    al,1            ;See if diskette is bootable
  2908.         jbe    osadd_add_11
  2909. jmp_osadd_error:
  2910.         jmp    osadd_error
  2911. osadd_add_11:
  2912.         call    chk_mboot_disk        ;See that proper disk is in
  2913.             mov     si,offset osadd_err9    ;  drive.
  2914.         jc    jmp_osadd_error
  2915.  
  2916.         cmp    opsys_ostype,50h
  2917.         je    osadd_add_14    
  2918.         mov    si,offset osadd_dos5    ;Ask user if installing DOS 5
  2919.         mov    di,50h
  2920.         cmp    opsys_clusters,0
  2921.         je    osadd_add_12
  2922.  
  2923.         mov    si,offset osadd_dos4    ;Ask user if installing DOS 4
  2924.         mov    di,40h
  2925.         cmp    huge_flag,0        ;If disk > 32 Meg, ask for 
  2926.         jne    osadd_add_12        ;   DOS 4
  2927.         cmp    dx,opsys_clusters
  2928.         ja    osadd_add_12
  2929.         mov    si,offset osadd_dos3    ;Ask user if installing DOS 3
  2930.         mov    di,30h
  2931.         cmp    cx,opsys_clusters
  2932.         jb    osadd_add_14
  2933. osadd_add_12:
  2934.         push    ax
  2935.         push    di
  2936.         mov    al,1            ;Set default to Yes
  2937.         call    msg_box
  2938.         pop    di
  2939.         pop    ax
  2940.         cmp    bl,1            ;See if answer Yes
  2941.         mov    si,offset osadd_err8
  2942.         jne    jmp_osadd_error
  2943.         mov    opsys_ostype,di        ;Save new opsys type
  2944. osadd_add_14:
  2945.         push    ax            ;Save os type
  2946.             mov     si,offset osadd_str7    ;Writing files message
  2947.             call    write_linenorm
  2948.         inc    opsys_count        ;Inc count of operating systems
  2949.         xor    bx,bx
  2950.         mov    bl,opsys_count        ;Get slot to place names
  2951.  
  2952.         mov    al,1              ;Copy BIOS param blk to  
  2953.         call    copy_bpb        ;  new boot record.
  2954.         pop    ax               ;Get opsys type
  2955.         mov    bp,ax
  2956.         call    put_opsys
  2957.  
  2958.         mov    si,offset osadd_err6    ;Error writing files
  2959.         jc    jmp_osadd_error
  2960.  
  2961.         mov    cx,4
  2962.         mov    si,offset opsys_table    ;Find first empty entry in
  2963.         xor    bx,bx            ;  the op sys table.
  2964. osadd_add_32:
  2965.         inc    bl
  2966.         cmp    byte ptr [si],80h
  2967.         jae    osadd_add_33
  2968.         add    si,NEXT_OSENTRY
  2969.         loop    osadd_add_32
  2970. osadd_add_33:
  2971.         mov    cx,opsys_ostype        ;Get DOS file config
  2972.         mov     ax,bp               ;Copy the op sys name from 
  2973.         call    copy_os_name        ;  the OEM name in the boot.
  2974.         xor    ax,ax
  2975.         mov    local_changed,1
  2976.         ret
  2977. osadd_error:
  2978.         call    scroll_half        ;Clear screen
  2979.         call    write_error        ;Print error message
  2980.         stc
  2981.         ret
  2982. osadd_add_opsys    endp
  2983.  
  2984. ;--------------------------------------------------------------------
  2985. ; OSADD DEL OPSYS - Deletes an operating system from the disk.
  2986. ;--------------------------------------------------------------------
  2987. osadd_del_opsys    proc    near
  2988.         mov    si,offset osadd_err2    ;Delete.  Don't delete active
  2989.         cmp    opsys_count,1        ;  OS files.
  2990.         jbe    osadd_error
  2991.  
  2992.         call    get_ostype        ;Query user for opsys
  2993.         mov    cx,4            
  2994.         mov    si,offset osadd_err7    ;Check to see if os is in use
  2995.         mov    di,offset ostype1
  2996. osadd_del_opsys_1:
  2997.         cmp    [di],bl
  2998.         je    osadd_error
  2999.         add    di,NEXT_ENTRY    
  3000.         loop    osadd_del_opsys_1
  3001.  
  3002.         call    delete_opsys        ;Erase op sys files
  3003. osadd_del_opsys_exit:
  3004.         dec    opsys_count
  3005.         xor    ax,ax
  3006.         mov    local_changed,1
  3007.         ret
  3008. osadd_del_opsys    endp
  3009.  
  3010. ;--------------------------------------------------------------------
  3011. ; OSADD REN OPSYS - Renames an operating system on the disk.
  3012. ;--------------------------------------------------------------------
  3013. osadd_ren_opsys    proc    near
  3014.         call    get_ostype        ;Query user for OP SYS
  3015.         or    bl,bl
  3016.         je    jmp_osadd_1
  3017.  
  3018.         push    di            ;Save ptr to op sys name
  3019.         mov    si,offset osadd_namestr
  3020.         xchg    di,si
  3021.         mov    cx,8            ;Only 8 characters in name
  3022.         rep     movsb
  3023.             mov     si,offset osadd_str4    ;Print old OS name
  3024.             call    write_linenorm          
  3025.  
  3026.             mov     si,offset osadd_str5    ;Prompt user for new OS name
  3027.             call    write_linenorm          
  3028.             mov     dx,0a29h
  3029.             mov     al,8            ;8 characters
  3030.             call    entry_box
  3031.             
  3032.         pop    di            ;Get pointer to table entry
  3033.             mov     si,bx            ;Copy ptr to new name
  3034.             rep     movsb            ;Copy name
  3035.         xor    ax,ax
  3036.         stosb                ;Terminate name
  3037.         mov    local_changed,1
  3038. jmp_osadd_1:
  3039.         xor    ax,ax
  3040.         ret
  3041. osadd_ren_opsys    endp
  3042.  
  3043. ;--------------------------------------------------------------------
  3044. ; OSADD EXIT - Sets the exit flag to return from this submenu
  3045. ;--------------------------------------------------------------------
  3046. osadd_exit    proc    near
  3047.         cmp    local_changed,0        
  3048.         clc
  3049.         je    osadd_exit_1
  3050.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  3051.             call    make_filename           ;  write opsys information.
  3052.  
  3053.         mov    si,dx            ;Copy ptr to ASCIIZ filename
  3054.         xor    cx,cx
  3055.         call    set_attributes        ;Clear file attributes
  3056.             mov     ax,3d02h
  3057.             int     21h
  3058.             jc      osadd_exit_error
  3059.  
  3060.         mov    bx,ax            ;Copy file handle
  3061.         mov    ax,4200h        ;Move file ptr to os table
  3062.         mov    dx,inst_boot_ptr
  3063.         xor    cx,cx
  3064.         int    21h        
  3065.             mov     ah,40h                  ;Write boot op sys data
  3066.             mov     dx,offset opsys_table
  3067.             mov     cx,inst_boot_size
  3068.             int     21h
  3069.             jc      osadd_exit_error
  3070.  
  3071.             mov     ah,3eh                  ;Close file
  3072.             int     21h
  3073.         mov    dx,si
  3074.         mov    cx,SYSFILE_ATTR
  3075.         call    set_attributes        
  3076.             jc      osadd_exit_error
  3077. osadd_exit_1:
  3078.         mov    al,-1            ;Set exit flag
  3079.             ret
  3080. osadd_exit_error:
  3081.         mov    si,offset osadd_err11
  3082.         stc
  3083.         jmp    short osadd_exit_1
  3084. osadd_exit    endp
  3085.  
  3086. main_osadd      endp
  3087.  
  3088. ;--------------------------------------------------------------------
  3089. ; MAIN DEFAULTS - Sets boot default values
  3090. ;--------------------------------------------------------------------
  3091. def_string1     db      20,08,"Current Defaults",0
  3092. def_string2     db      25,10,"Default Session:",0
  3093. def_string3     db      25,12,"Default Timeout:",0
  3094. def_string4     db      46,12,"Seconds",0
  3095. def_string6     db      15,14,"Enter Timeout Value in Seconds",0
  3096.  
  3097. default_msg1    db      "Defaults Not Changed",0
  3098. default_msg2    db      "No Default Session",0
  3099. default_msg3    db      "Indefinite  ",0
  3100. default_err1    db      "Invalid number",0
  3101.  
  3102. local_timeout   dw      0
  3103. local_default   db      0
  3104.  
  3105. def_chdef       db      "Change Default Session",0
  3106. def_chtime      db      "Change Timeout",0
  3107.  
  3108. default_table    dw    offset default_menu
  3109.         dw    offset default_ch_def
  3110.         dw    offset default_ch_time
  3111.         dw    offset default_exit
  3112.         dw    offset add_quit
  3113.  
  3114. default_menu    db      4,0                     ;Number of choices, Selected
  3115.             db      30,22                   ;Location of "Choices" prompt
  3116.             dw      0                       ;Timeout value
  3117.             db      0,0                     ;Col, Row of Timeout string
  3118.             db      25,17                   ;Column, Row of menu item
  3119.             dw      offset def_chdef        ;Offset of menu text
  3120.             db      25,18
  3121.             dw      offset def_chtime
  3122.             db      25,19
  3123.             dw      offset return_text
  3124.             db      25,20
  3125.             dw      offset quit_text
  3126.  
  3127. main_defaults   proc    near
  3128.             assume  cs:code,ds:code
  3129.             mov     al,boot_default         ;Copy system values to local
  3130.             mov     local_default,al        ;  variables.
  3131.             mov     ax,boot_timeout
  3132.             mov     local_timeout,ax
  3133. main_default_0:
  3134.             mov     si,offset def_string1
  3135.             call    write_linenorm
  3136.             mov     si,offset def_string2
  3137.             call    write_linenorm
  3138.             mov     si,offset def_string3
  3139.             call    write_linenorm
  3140.             mov     si,offset def_string4
  3141.             call    write_linenorm
  3142. main_default_1:
  3143.             mov     si,offset default_msg2  ;Point to no default msg
  3144.             xor     bx,bx
  3145.             or      bl,local_default        ;Get pointer to default entry
  3146.             je      main_default_3
  3147.             call    get_entry
  3148.             mov     si,bx
  3149. main_default_3:
  3150.             mov     dx,0a2ah                ;Row 10, Col 42
  3151.             call    write_line_at           ;Write string
  3152.  
  3153.             mov     ax,local_timeout        ;Get timeout value
  3154.         or    ax,ax
  3155.         jne    main_default_4
  3156.         mov    si,offset default_msg3    ;No timeout message
  3157.         mov    dx,0c2ah
  3158.         call    write_line_at
  3159.         jmp    short main_default_5
  3160. main_default_4:
  3161.             xor     dx,dx                   ;Convert to seconds
  3162.             mov     bx,18
  3163.             div     bx
  3164.             mov     dx,0c2ah                ;Write default timeout
  3165.             call    hex2asc
  3166. main_default_5:
  3167.             mov     si,offset default_table
  3168.             mov     al,1
  3169.             call    jump_menu
  3170.         cmp    al,-1
  3171.         jne    main_default_0
  3172.         mov    al,local_changed
  3173.         ret
  3174.  
  3175. ;--------------------------------------------------------------------
  3176. ; DEFAULT CH DEF - Changes the default session
  3177. ;--------------------------------------------------------------------
  3178. default_ch_def    proc    near
  3179.             mov     al,local_default        ;To select default session,
  3180.             call    get_session             ;  display menu of all
  3181.                                             ;  sessions.
  3182.             jc      default_ch_def_1    ;If carry set or no selection
  3183.         or    bl,bl            ;  skip default set.
  3184.             jc      default_ch_def_1
  3185.             mov     local_default,bl        ;Set new default
  3186.         mov    local_changed,1
  3187. default_ch_def_1:
  3188.         xor    al,al
  3189.             ret
  3190. default_ch_def    endp
  3191.  
  3192. ;--------------------------------------------------------------------
  3193. ; DEFAULT CH TIME - Changes the default timeout.
  3194. ;--------------------------------------------------------------------
  3195. default_ch_time    proc    near
  3196.             mov     si,offset def_string6
  3197.             call    write_linenorm
  3198.  
  3199.             mov     dx,0e2fh                ;Set cursor
  3200.             mov     al,3                    ;Allow 3 characters
  3201.             call    get_number
  3202.             jc      default_ch_time_1       ;Carry set, error
  3203.  
  3204.             mov     dx,18                   ;Convert seconds to ticks
  3205.             mul     dx
  3206.             mov     local_timeout,ax
  3207.         mov    local_changed,1
  3208.             call    scroll_half
  3209.             ret
  3210. default_ch_time_1:
  3211.             call    scroll_half
  3212.             mov     si,offset default_err1  ;Illegal number
  3213.             call    write_error
  3214.         ret
  3215. default_ch_time    endp
  3216.  
  3217. ;--------------------------------------------------------------------
  3218. ; DEFAULT_EXIT - Copys the new default values to the boot table.
  3219. ;--------------------------------------------------------------------
  3220. default_exit     proc    near
  3221.             mov     al,local_default        ;Copy local value to system
  3222.             mov     boot_default,al         ;  values.
  3223.             mov     ax,local_timeout
  3224.             mov     boot_timeout,ax
  3225.         mov    al,-1
  3226.             ret
  3227. default_exit    endp
  3228. main_defaults   endp
  3229.  
  3230. ;--------------------------------------------------------------------
  3231. ; INST INSTALL - Installs MultiBoot on a system.
  3232. ;--------------------------------------------------------------------
  3233. install_msg1    db    15,9,"WARNING!  You should back up your"
  3234.         db    " disk before",0
  3235. install_msg2    db    25,10,"installing MultiBoot.",0
  3236.  
  3237. install_msg    db    15,16,"Do You wish to install MultiBoot?",0
  3238. install1_msg    db    15,16,"Installing MultiBoot.  Please wait.",0
  3239. install_nomsg    db    "MultiBoot not installed",0
  3240.  
  3241. main_install    proc    near
  3242.             assume  cs:code,ds:code
  3243.             cmp     installed_flag,0    ;See if already installed
  3244.             je      install_0
  3245.             mov     si,offset errmsg21
  3246.             jmp     install_error1
  3247. install_0:
  3248.             mov     si,offset install_msg1
  3249.             call    write_linenorm
  3250.             mov     si,offset install_msg2
  3251.             call    write_linenorm
  3252.         mov    si,offset install_msg
  3253.         mov    al,1            ;Set default to Yes
  3254.         call    msg_box
  3255.         cmp    bl,1            ;See if answer Yes
  3256.         je    install_01
  3257.         mov    si,offset install_nomsg    ;Answer No, abort install.
  3258.         jmp    install_error1
  3259. install_01:
  3260.         mov    si,offset install1_msg    
  3261.         call    write_linenorm
  3262.  
  3263.         mov    al,drive_letter
  3264.         call    get_opsys        ;Get operating system
  3265.             jc      jmp_install_error
  3266.  
  3267.         mov    bx,101h            ;Write operating system with
  3268.         call    put_opsys        ;  bootfile = LASTBOOT.BIN
  3269.         jc    jmp_install_error
  3270.         
  3271.             mov     si,offset mboot_name    ;Write Boot extend file 
  3272.             call    make_filename           
  3273.             mov     si,offset boot_extend_start
  3274.             mov     cx,offset install_start - offset boot_extend_start
  3275.          mov    ax,SYSFILE_ATTR
  3276.         mov    no_DOS_flag,0    
  3277.         call    write_file
  3278.         mov    no_DOS_flag,1    
  3279.         jc    jmp_install_error
  3280. ; Modify Multiboot boot record with data from original boot record.
  3281.             push    ds                         ;Compute the amount of
  3282.             lds     si,databuff_ptr            ;  boot data on old boot
  3283.             mov     di,100h                    ;  record.  If too much,
  3284.             mov     cx,ds:[si+1]               ;  don't install.
  3285.             add     cx,3
  3286.             cmp     byte ptr ds:[si],0e9h      ;See if long jump
  3287.             je      install_2
  3288.             cmp     byte ptr ds:[si],0ebh      ;See if short jmp
  3289.             je      install_1
  3290.             pop     ds
  3291. jmp_install_error:
  3292.             jmp     install_error        ;If not a jump, error
  3293. install_1:
  3294.             xor     cx,cx
  3295.             mov     cl,ds:[si+1]            ;Get size of data area
  3296.             add     cx,2                    ;Add room for jmp
  3297. install_2:
  3298.             cmp     cx,offset bootcode - offset entry
  3299.             ja      install_error
  3300.             rep     movsb                   ;Copy boot data
  3301.             pop     ds
  3302.             mov     byte ptr cs:entry,0e9h   ;Copy jump opcode
  3303.             mov     dx,offset bootcode - 103h  ;Compute the jump value
  3304.             mov     word ptr cs:entry[1],dx
  3305.  
  3306.             mov     ax,dos_version
  3307.             cmp     ax,300h                 ;If DOS 2.x clear hidden sec
  3308.             ja      install_3               ;  count.
  3309.         mov    bp,100h
  3310.             mov     word ptr num_hidden_sec,0
  3311.             cmp     ax,314h                 ;If DOS 3.0 - 3.2, clear high
  3312.             ja      install_3               ;  word.
  3313.             mov     word ptr num_hidden_sec[2],0
  3314. install_3:
  3315. ; Write Multiboot boot record to target drive.
  3316.             mov     al,drive_letter
  3317.             mov     bx,offset entry         ;Get ptr to boot record
  3318.         call    put_bootrec
  3319.             jc      install_error
  3320.  
  3321.         mov    cx,4
  3322.         mov    si,offset opsys_table
  3323.         add    si,OPSYS_TYPE
  3324.         mov    bl,1
  3325. install_4:    
  3326.         cmp    word ptr [si],100h    ;See if OS/2 installed on
  3327.         je    install_5        ;  disk.
  3328.         inc    bl
  3329.         add    si,NEXT_OSENTRY
  3330.         loop    install_4
  3331.         jmp    short install_6
  3332. install_5:
  3333.         call    make_os_names
  3334.         call    make_filename
  3335.         mov    di,si
  3336.         mov    dx,offset os2boot_aname
  3337.         call    copy_file
  3338.         mov    dx,di            ;Hide boot file.
  3339.         mov    cx,SYSFILE_ATTR
  3340.         call    set_attributes        
  3341. install_6:
  3342.             mov     changed_flag,0
  3343.             mov     installed_flag,1        ;Set install flag
  3344.             xor     al,al                   ;Clear error flag
  3345. install_exit1:
  3346.             ret
  3347. install_error:
  3348.             mov     si,offset errmsg20
  3349. install_error1:
  3350.             stc
  3351.             jmp     short install_exit1
  3352. main_install    endp
  3353.  
  3354. ;--------------------------------------------------------------------
  3355. ; INST REMOVE - Removes Multiboot from a system.
  3356. ;--------------------------------------------------------------------
  3357. remove_msg    db    15,16,"Do you wish to remove MultiBoot?",0
  3358. remove1_msg    db    15,16,"Removing MultiBoot.  Please wait.",0
  3359. remove_nomsg    db    "MultiBoot not removed",0
  3360.  
  3361. main_remove     proc    near
  3362.             assume  cs:code,ds:code
  3363. ; Check to see if already installed
  3364.             cmp     installed_flag,0    ;If not installed, don't
  3365.             jne     remove_1        ;  remove.
  3366.             mov     si,offset errmsg23
  3367.             jmp     remove_error1
  3368. remove_1:
  3369.         mov    si,offset remove_msg    ;Verify remove request.
  3370.         mov    al,1            ;Set default to Yes
  3371.         call    msg_box
  3372.         cmp    bl,1            ;See if answer Yes
  3373.         mov    si,offset remove_nomsg
  3374.         jne    remove_error1
  3375.  
  3376.         mov    si,offset remove1_msg    ;Indicate removing.
  3377.         call    write_linenorm
  3378.  
  3379.         mov    si,offset lastboot_name    ;Read current op sys boot
  3380.         call    make_filename          ;  record from the file.
  3381.         push    es
  3382.         les    si,databuff_ptr
  3383.         call    read_file        ;Read LASTBOOT.BIN
  3384.         pop    es
  3385.             jc      remove_error
  3386. ;Write old boot record to boot sector
  3387.             mov     al,drive_letter
  3388.             push    ds
  3389.             lds     bx,databuff_ptr         ;Get ptr to data buffer
  3390.             call    put_bootrec             ;Write the boot record
  3391.             pop     ds
  3392.             jc      remove_error
  3393.  
  3394.         call    fixup_fat        ;Remove bad sectors in FAT
  3395.  
  3396.             mov     si,offset mboot_name    ;Delete MBOOT.SYS
  3397.         call    delete_file
  3398.         mov    si,offset lastboot_name    ;Delete LASTBOOT.BIN
  3399.         call    delete_file
  3400.  
  3401.         mov    cx,4
  3402.         mov    si,offset opsys_table    ;Scan operating system table
  3403.         xor    bx,bx            ;  deleteing the MBOOTOS files
  3404. remove_2:
  3405.         inc    bl
  3406.         cmp    byte ptr [si],80h    ;Is OS entry used?
  3407.         jae    remove_3
  3408.         call    delete_opsys
  3409. remove_3:
  3410.         add    si,NEXT_OSENTRY
  3411.         loop    remove_2
  3412.  
  3413.             mov     changed_flag,0
  3414.             mov     installed_flag,0        ;Clear install flag
  3415.         call    scroll_half        ;Clear screen
  3416.             clc                             ;Clear error flag
  3417.         mov    al,-1            ;Set terminate flag
  3418. remove_exit1:
  3419.             ret
  3420. remove_error:
  3421.             mov     si,offset errmsg22
  3422. remove_error1:
  3423.             stc
  3424.         mov    al,0
  3425.             jmp     short remove_exit1
  3426. main_remove     endp
  3427.  
  3428. ;--------------------------------------------------------------------
  3429. ; EXIT - Updates changes to installed files and exits program.
  3430. ;--------------------------------------------------------------------
  3431. exit_str0       db      15,14,"MultiBoot not installed.",0
  3432. exit_str1       db      15,16,"Do you wish to install MultiBoot?",0
  3433. exit_err1    db    "Installed data incompatible with this version.",0
  3434. exit            proc    near
  3435.             assume  cs:code,ds:code
  3436.         cmp    installed_flag,0    ;If not installed, ask if 
  3437.         jne    exit_1            ;  prog should install.
  3438.         mov    si,offset exit_str0
  3439.         call    write_linenorm
  3440.         mov    al,1            ;Default Yes
  3441.         mov    si,offset exit_str1        
  3442.         call    msg_box    
  3443.         cmp    bl,1
  3444.         jne    exit_3
  3445.         call    main_install        ;Install Multiboot
  3446.         jc    exit_4            
  3447.         jmp    short exit_3
  3448. exit_1:
  3449.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  3450.             call    make_filename           ;  write updated information.
  3451.  
  3452.         mov    si,dx            ;Copy ptr to ASCIIZ filename
  3453.         xor    cx,cx
  3454.         call    set_attributes        ;Clear file attributes
  3455.             mov     ax,3d02h
  3456.             int     21h
  3457.             jc      exit_3
  3458.  
  3459.         mov    bx,ax            ;Copy file handle
  3460.         mov    ax,4200h        ;Move file ptr to boot table
  3461.         mov    dx,inst_data_ptr
  3462.         xor    cx,cx
  3463.         int    21h        
  3464.             mov     ah,40h                  ;Write boot data
  3465.             mov     dx,offset boot_data1
  3466.             mov     cx,inst_data_size
  3467.             int     21h
  3468.  
  3469.         mov    ax,4200h        ;Move file ptr to boot table
  3470.         mov    dx,inst_sess_ptr
  3471.         xor    cx,cx
  3472.         int    21h        
  3473.             mov     ah,40h                  ;Write boot session data
  3474.             mov     dx,offset boot_array
  3475.             mov     cx,inst_sess_size
  3476.             int     21h
  3477.  
  3478.         mov    ax,4200h        ;Move file ptr to os table
  3479.         mov    dx,inst_boot_ptr
  3480.         xor    cx,cx
  3481.         int    21h        
  3482.             mov     ah,40h                  ;Write boot op sys data
  3483.             mov     dx,offset opsys_table
  3484.             mov     cx,inst_boot_size
  3485.             int     21h
  3486.  
  3487.             mov     ah,3eh                  ;Close file
  3488.             int     21h
  3489.         mov    dx,si
  3490.         mov    cx,SYSFILE_ATTR
  3491.         call    set_attributes        
  3492. exit_3:
  3493.             mov     al,-1            ;Set flag to end program
  3494. exit_4:
  3495.             ret
  3496. exit            endp
  3497.  
  3498. ;--------------------------------------------------------------------
  3499. ; QUIT - Quits program without changing installed files.
  3500. ;--------------------------------------------------------------------
  3501. quit_msg    db    20,15,"Do you wish to discard all changes made?",0
  3502. quit_msg1    db    20,9,"You have choosen to leave MultiBoot without",0
  3503. quit_msg2    db    17,10,"making your changes permanent.  To make your",0
  3504. quit_msg3    db    17,11,"changes permanent, answer No, then select",0
  3505. quit_msg4    db    17,12,"Update and Exit MultiBoot on the Main Menu.",0
  3506. quit            proc    near
  3507.             assume  cs:code,ds:code
  3508.         cmp    changed_flag,0
  3509.         je    quit_1
  3510.         mov    si,offset quit_msg1    ;Tell user what he/she is
  3511.         call    write_linenorm        ;  doing.
  3512.         mov    si,offset quit_msg2
  3513.         call    write_linenorm
  3514.         mov    si,offset quit_msg3
  3515.         call    write_linenorm
  3516.         mov    si,offset quit_msg4
  3517.         call    write_linenorm
  3518.         mov    si,offset quit_msg
  3519.         mov    al,2            ;Set default to No.
  3520.         call    msg_box
  3521.         mov    al,0
  3522.         cmp    bl,2            ;See if No.
  3523.         je    quit_2
  3524. quit_1:
  3525.         call    scroll_half
  3526.             mov     al,-1            ;Set terminate prog flag
  3527. quit_2:
  3528.             ret
  3529. quit            endp
  3530.  
  3531. ;--------------------------------------------------------------------
  3532. ; JUMP MENU - Displays a menu then calls the routines pointed to in
  3533. ;             in the jump table.
  3534. ; Entry: AL - Default selection
  3535. ;        SI - Offset of jump table 
  3536. ;--------------------------------------------------------------------
  3537. jump_menu       proc    near
  3538.             mov     bp,[si]                 ;Display main menu.
  3539.             mov     byte ptr [bp+MENU_SELECTED],al
  3540.         push    si
  3541.             call    menu
  3542.         pop    si
  3543.             jnc     jump_menu_2             ;Esc pressed -> Assume quit
  3544. jump_menu_1:
  3545.         mov    bl,[bp]            ;BL = last  choice
  3546. jump_menu_2:
  3547.             or      bl,bl                   ;If no cmd, assume quit.
  3548.             je      jump_menu_1        ;Convert menu choice to
  3549.             shl     bx,1                    ;  index into jump table of
  3550.             add     bx,si                   ;  routines.
  3551.             call    scroll_half        ;Clear lower half of screen.
  3552.         call    [bx]            ;Call routine.
  3553.             ret
  3554. jump_menu       endp
  3555.  
  3556. ;--------------------------------------------------------------------
  3557. ; GET SESS NAME - Querys the user for a session name
  3558. ; Entry: BL - Ptr to session entry
  3559. ; Exit:  CF - Set if Ctrl-C entered.
  3560. ;--------------------------------------------------------------------
  3561.  
  3562. get_sess_name   proc    near
  3563.         mov    ax,offset local_add1    ;Compute entry into 
  3564.         call    get_entry1        ;  local table.
  3565.         mov    bp,bx            ;Save ptr to table entry
  3566.             call    scroll_half             ;Clear screen
  3567.  
  3568.             mov     dx,0806h                ;Write header.
  3569.             mov     si,offset inst_text1
  3570.         call    write_line_at
  3571.  
  3572.             mov     di,bp                   ;Write session data to screen
  3573.             mov     dx,0a06h
  3574.             call    disp_session
  3575.  
  3576.         mov    si,offset add_str_msg1    ;Print message on how to
  3577.         call    write_linenorm        ;  return to add menu.
  3578.  
  3579.             mov     si,offset add_str4      ;Prompt user for Session name
  3580.             call    write_linenorm             
  3581.             mov     dx,0e34h                   
  3582.             mov     al,offset auto1 - offset name1 - 1
  3583.             call    entry_box
  3584.         jc    get_sess_exit
  3585.             mov     si,bx
  3586.             mov     di,bp                   ;Copy title to local buffer.
  3587.             rep     movsb
  3588.             mov     byte ptr [di],0         ;Terminate string
  3589.             mov     dh,14
  3590.             call    clear_line
  3591. get_sess_exit:
  3592.         ret
  3593. get_sess_name    endp
  3594.  
  3595. ;--------------------------------------------------------------------
  3596. ; ADD FILE - Asks user for a filename and verifys its correctness.
  3597. ; Entry: SI - Pointer to filename (CONFIG or AUTOEXEC)
  3598. ;--------------------------------------------------------------------
  3599. add_file_str    db      05,14,"Enter the file that will become the "
  3600. add_file_name   db      12 dup (" ")
  3601. add_file_str1   db      " file:",0
  3602.  
  3603. add_file_str2   db      05,14,"The file "
  3604. add_file_name0    db    12 dup (" ")
  3605.         db    "does not exist.",0
  3606. add_file_str3   db      05,16,"Do you want to copy the current "
  3607. add_file_name1  db      12 dup (" ")
  3608.             db      " file into this one?",0
  3609.  
  3610. add_file_err1   db      "A filename must be entered",0
  3611.  
  3612. add_file_err2   db      "The filename "
  3613. add_file_name2  db      12 dup (" ")
  3614.             db      " cannot be used",0
  3615.  
  3616. add_file_err3   db      "Error creating file",0
  3617. add_file_err4   db      "This file does not exist",0
  3618.  
  3619. add_file        proc    near
  3620.             push    si                      ;Save ptr to filename
  3621.  
  3622.             mov     dh,10
  3623.             call    clear_line
  3624.             mov     di,local_selection      ;Write session data to screen
  3625.             call    disp_session
  3626.  
  3627.             mov     al," "                  ;Clear file names from strings
  3628.             mov     di,offset add_file_name
  3629.             mov     cx,12
  3630.             rep     stosb
  3631.             mov     di,offset add_file_name0
  3632.             mov     cx,12
  3633.             rep     stosb
  3634.             mov     di,offset add_file_name1
  3635.             mov     cx,12
  3636.             rep     stosb
  3637.             mov     di,offset add_file_name2
  3638.             mov     cx,12
  3639.             rep     stosb
  3640.  
  3641.             pop     bp            ;Get ptr to filename
  3642.         mov    si,bp            
  3643.             mov     di,offset add_file_name
  3644.             call    fn2asciiz
  3645.             mov     bx,cx
  3646.             mov     byte ptr [bx+si]," "    ;Erase zero
  3647.  
  3648.             push    si                       ;Copy filename to other
  3649.             mov     di,offset add_file_name1 ;  messages
  3650.             push    cx
  3651.             rep     movsb
  3652.             pop     cx
  3653.             pop     si
  3654.             mov     di,offset add_file_name2
  3655.             rep     movsb
  3656. add_file_1:
  3657.             mov     dh,14                   ;Clear line for query.
  3658.             call    clear_line
  3659.  
  3660.             mov     si,offset add_file_str  ;Assemble prompt message using
  3661.             call    write_linenorm          ;  destination filename
  3662.             mov     si,offset add_file_str1 ;  provided.
  3663.             call    write_linenorm
  3664.  
  3665.         mov    si,offset add_str_msg1    ;Print message on how to
  3666.         call    write_linenorm        ;  return to add menu.
  3667.  
  3668.             mov     dx,0e3ch                ;Get filename max char = 12
  3669.             mov     al,12
  3670.             call    entry_box
  3671.         pushf
  3672.             mov     dh,22            ;Erase ctl-break message
  3673.             call    clear_line
  3674.         popf
  3675.         jnc    add_file_11
  3676.         jmp    add_file_4
  3677. add_file_11:
  3678.             or      cx,cx                   ;If zero length string, error
  3679.             mov     si,offset add_file_err1
  3680.             je      add_file_error
  3681.             mov     si,cx
  3682.             mov     byte ptr [bx+si],0      ;Terminate name with zero
  3683.  
  3684.             push    cx
  3685.             mov     si,bx
  3686.             mov     di,offset temp_buff
  3687.             call    asciiz2fn
  3688.             mov     di,bp                   ;Make sure destination name
  3689.             mov     cx,11                   ;  not used.
  3690.             repe    cmpsb
  3691.             pop     cx
  3692.             jne     add_file_2
  3693.             mov     si,offset add_file_err2 ;Can't use dest filename
  3694. add_file_error:
  3695.             call    write_error
  3696.             jmp     short add_file_1
  3697. add_file_2:
  3698.             mov     si,offset temp_buff     ;Create filename from 8.3 
  3699.             call    make_filename           ;  format.
  3700.  
  3701.             mov     ax,3d00h                ;Open file, read only
  3702.             int     21h
  3703.             jnc     add_file_3
  3704.  
  3705.         mov    si,offset temp_buff    ;Add filename to error msg
  3706.             mov     di,offset add_file_name0
  3707.             call    fn2asciiz
  3708.             mov     bx,cx
  3709.             mov     byte ptr [bx+si]," "    ;Erase terminating zero
  3710.  
  3711.             mov     si,offset add_file_err4 ;Indicate to the user that
  3712.             call    write_error             ;  the file can't be found.
  3713.  
  3714.             mov     si,bp                   ;Get destination file
  3715.         call    find_file
  3716.             jc      add_file_1              ;If no file, skip copy question
  3717.  
  3718.             mov     dh,14                   ;File does not exist, prompt
  3719.             call    clear_line              ;  user for choices.
  3720.  
  3721.             mov     si,offset add_file_str2
  3722.             call    write_linenorm
  3723.             mov     al,1                    ;Set default answer
  3724.             mov     si,offset add_file_str3 ;See if user wants to copy
  3725.             call    msg_box                 ;  the current autoexec or
  3726.             mov     dh,14                   ;  config file to this one.
  3727.             call    clear_line
  3728.             cmp     bl,1                    ;If not Yes, skip copy.
  3729.             je      add_file_21
  3730.             jmp     add_file_1
  3731. add_file_21:
  3732.         mov    si,bp            
  3733.             mov     di,offset temp_buff+40
  3734.             call    make_filename
  3735.             mov     di,offset filename_buff    ;Copy autoexec or config to
  3736.             call    copy_file        ;  new filename
  3737.             mov     si,offset add_file_err3
  3738.             jc      add_file_error
  3739. add_file_3:
  3740.             mov     si,offset temp_buff     ;Point SI to new filename
  3741.             clc
  3742. add_file_4:
  3743.             ret
  3744. add_file        endp
  3745.  
  3746. ;--------------------------------------------------------------------
  3747. ; GET SESSION - Displays a session menu.
  3748. ; Entry: AL - Default session.
  3749. ; Exit:  BX - Session number selected.
  3750. ;--------------------------------------------------------------------
  3751. get_sess_str    db      20,7,"Select Session",0
  3752. get_session     proc    near
  3753.         mov    bx,1            ;If only one session, don't
  3754.         cmp    session_count,1        ;  ask user to pick.
  3755.         ja     get_session_1
  3756.         jmp    short get_session_3
  3757. get_session_1:
  3758.             mov     bp,offset boot_menu
  3759. get_session_2:
  3760.             push    ax
  3761.             call    scroll_half              ;Clear screen.
  3762.             mov     si,offset get_sess_str   ;Display message
  3763.             call    write_linenorm
  3764.             pop     ax
  3765.             mov     [bp+MENU_SELECTED],al   ;Set default
  3766.             mov     word ptr [bp+MENU_TIMEOUT],0
  3767.             call    menu
  3768. get_session_3:
  3769.             pushf                           ;Carry indicates <esc> pressed
  3770.             call    scroll_half
  3771.             popf
  3772.             ret
  3773. get_session     endp
  3774.  
  3775. ;--------------------------------------------------------------------
  3776. ; GET OSTYPE - Prompts the user to select an operating system.
  3777. ; Exit:   BL - OS selection
  3778. ;--------------------------------------------------------------------
  3779. os_menu_str1    db      05,14,"Select Operating System",0
  3780.  
  3781. os_menu         db      4,1                     ;Number of choices, Selected
  3782.             db      30,22                   ;Location of "Choices" prompt
  3783.             dw      0                       ;Timeout value
  3784.             db      0,0                     ;Col, Row of Timeout string
  3785.             db      25,17                   ;Column, Row of menu item
  3786.             dw      offset os_name1         ;Offset of menu text
  3787.             db      25,18
  3788.             dw      offset os_name2
  3789.             db      25,19
  3790.             dw      offset os_name3
  3791.             db      25,20
  3792.             dw      offset os_name4
  3793.  
  3794. get_ostype    proc    near
  3795.             mov     si,offset os_menu_str1  ;Prompt user for the
  3796.             call    write_linenorm          ;  operating system 
  3797.             mov     bp,offset os_menu       ;Operating system menu
  3798.             call    menu
  3799.         pushf
  3800.             mov     cx,0e00h                ;Clear screen
  3801.             mov     dx,1950h
  3802.             call    scroll_block
  3803.         xor    di,di
  3804.         popf                ;If <esc> no choice made
  3805.         jc    get_ostype_exit
  3806.         call    get_os_entry
  3807.         clc
  3808. get_ostype_exit:
  3809.         ret
  3810. get_ostype    endp
  3811.  
  3812. ;--------------------------------------------------------------------
  3813. ; MAKE FILENAME - Adds drive and directory stuff to 8.3 filename.
  3814. ; Entry: SI - Pointer to filename
  3815. ; Exit:  SI = DX - Pointer to filename
  3816. ;--------------------------------------------------------------------
  3817. make_filename   proc    near
  3818.         push    cx
  3819.         push    di
  3820.             mov     di,offset filename_buff
  3821.         push    di
  3822.             mov     al,drive_letter         ;Copy drive letter
  3823.             stosb
  3824.             mov     ax,"\:"                 ;Add DOS dir stuff
  3825.             stosw
  3826.             call    fn2asciiz               ;Append filename
  3827.             pop     si
  3828.             mov     dx,si                   ;Copy pointer to filename
  3829.         pop    di
  3830.         pop    cx
  3831.             ret
  3832. make_filename   endp
  3833.  
  3834. ;--------------------------------------------------------------------
  3835. ; READ FILE - Opens a file, reads the data, and closes the file.
  3836. ; Entry: DS:DX - Pointer to source ASCIIZ filename
  3837. ;        ES:SI - Pointer to data buffer
  3838. ; Exit:     CX - Bytes read
  3839. ;--------------------------------------------------------------------
  3840. read_file    proc    near
  3841.         call    set_crit_vec        ;Set crit vec to int routine
  3842.             mov     ax,3d00h                ;Open file, read only
  3843.             int     21h
  3844.         jc    read_file_exit
  3845.             mov     bx,ax                   ;Copy file handle
  3846.  
  3847.             push    ds                      ;Read file into data buffer
  3848.         push    es
  3849.         pop    ds
  3850.             mov     dx,si        
  3851.             mov     cx,65013                ;Buffer size
  3852.             mov     ah,3fh                  ;Read file
  3853.             int     21h
  3854.             mov     cx,ax                   ;Save bytes read
  3855.              pop     ds
  3856.         jc    read_file_exit
  3857.  
  3858.             mov     ah,3eh                  ;Close file
  3859.             int     21h
  3860. read_file_exit:
  3861.             call    reset_crit_vec        ;Restore critical error vec
  3862.         ret
  3863. read_file    endp
  3864.  
  3865. ;--------------------------------------------------------------------
  3866. ; WRITE FILE - Creates a file and writes data to the file
  3867. ; Entry:    AX - Attributes for destination file
  3868. ;           CX - Size of data
  3869. ;        DS:DX - Pointer to desination  ASCIIZ filename
  3870. ;        ES:SI - Pointer to data 
  3871. ;--------------------------------------------------------------------
  3872. write_file      proc    near
  3873.         push    cx            ;Save size of data
  3874.         call    set_crit_vec        ;Set crit vec to int routine
  3875.             mov     cx,ax                   ;Copy attributes
  3876.             mov     ah,3ch                  ;Create file.
  3877.             int     21h
  3878.             mov     bx,ax                   ;Copy file handle
  3879.         pop    cx            ;Restore data size
  3880.             jc      write_file_exit
  3881.  
  3882.         push    ds
  3883.         push    es
  3884.         pop    ds
  3885.         mov    dx,si            ;Copy pointer to data
  3886.             mov     ah,40h                  ;Write file
  3887.             int     21h
  3888.         pop    ds
  3889.         jc    write_file_exit
  3890.             mov     ah,3eh                  ;Close file
  3891.             int     21h
  3892. write_file_exit:
  3893.             call    reset_crit_vec        ;Restore critical error vec
  3894.             ret
  3895. write_file      endp
  3896.  
  3897. ;--------------------------------------------------------------------
  3898. ; READ ABSOLUTE - Reads sectors from the disk.
  3899. ; Entry:   AL - Letter of drive to read
  3900. ;          CX - Number of sectors to read.  
  3901. ;       SI,DX - Sector to start read (SI only used on huge disks)
  3902. ;       DS:BX - Pointer to data buffer. 
  3903. ;--------------------------------------------------------------------
  3904. read_abs_hstruc    =    $            ;Needed for >32M disks
  3905. read_abs_start    dd    0            ;Starting sector
  3906. read_abs_cnt    dw    0            ;Number of sectors to read
  3907. read_abs_dbp    dd    0            ;Data buffer ptr
  3908.  
  3909. read_absolute   proc    near
  3910.         push    bx
  3911.         push    cx
  3912.         push    ds
  3913.         call    set_crit_vec        ;Set crit vec to int routine
  3914.         call    huge_disk_check
  3915.         jc    read_abs_2
  3916.         je    read_abs_1
  3917.         push    ds            ;Save ptr to data buffer
  3918.         push    bx
  3919.         push    cs
  3920.         pop    ds
  3921.         mov    bx,offset read_abs_hstruc
  3922.         mov    [bx],dx            ;More than 64K sectors
  3923.         mov    [bx+2],si        ;  -> huge disk uses a
  3924.         mov    [bx+4],cx        ;  different format
  3925.         pop    [bx+6]            ;  than std int 25h.    
  3926.         pop    [bx+8]
  3927.         mov    cx,-1
  3928. read_abs_1:
  3929.             sub     al,'A'            ;Convert to hex (0 base)
  3930.             int     25h                     ;DOS Absolute Disk Read
  3931.             pop     bx                      ;Clean off old flags
  3932.             cld
  3933. read_abs_2:
  3934.             call    reset_crit_vec        ;Restore critical error vec
  3935.         pop    ds
  3936.         pop    cx
  3937.         pop    bx
  3938.             ret
  3939. read_absolute   endp
  3940.  
  3941. ;--------------------------------------------------------------------
  3942. ; WRITE ABSOLUTE - Writes sectors to the disk.
  3943. ; Entry:   AL - Letter of drive to write
  3944. ;          CX - Number of sectors to write  
  3945. ;       SI,DX - Sector to start write (SI only used on huge disks)
  3946. ;       DS:BX - Pointer to data buffer. 
  3947. ;--------------------------------------------------------------------
  3948. write_absolute  proc    near
  3949.         push    bx
  3950.         push    cx
  3951.         push    ds
  3952.         call    set_crit_vec        ;Set crit vec to int routine
  3953.         call    huge_disk_check
  3954.         jc    write_abs_2    
  3955.         je    write_abs_1
  3956.         push    ds            ;Save data buffer pointer
  3957.         push    bx
  3958.         push    cs
  3959.         pop    ds
  3960.         mov    bx,offset read_abs_hstruc
  3961.         mov    [bx],dx            ;More than 64K sectors
  3962.         mov    [bx+2],si        ;  -> huge disk uses a
  3963.         mov    [bx+4],cx        ;  different format
  3964.         pop    [bx+6]            ;  than std int 26h.    
  3965.         pop    [bx+8]
  3966.         mov    cx,-1                
  3967. write_abs_1:
  3968.             sub     al,'A'            ;Convert to hex (0 based)
  3969.             int     26h                     ;DOS Absolute Disk Write
  3970.             pop     bx                      ;Clean off old flags
  3971.             cld
  3972. write_abs_2:
  3973.             call    reset_crit_vec        ;Restore critical error vec
  3974.         pop    ds
  3975.         pop    cx
  3976.         pop    bx
  3977.             ret
  3978. write_absolute  endp
  3979.  
  3980. ;--------------------------------------------------------------------
  3981. ; HUGE DISK CHECK - Checks if disk is greater than 32 Meg
  3982. ; Entry: AL - Disk to check
  3983. ; Exit:  ZF - Clear if > 32 Meg disk
  3984. ;        CF - Set if error
  3985. ;        DI - Sectors per cluster
  3986. ;--------------------------------------------------------------------
  3987. last_disk_read    db    -1
  3988. last_disk_huge    db    0
  3989. last_disk_spc     dw    0
  3990. huge_disk_check    proc    near
  3991.         push    ax
  3992.         push    bx
  3993.         push    cx
  3994.         push    dx
  3995.         cmp    al,last_disk_read    ;Save last disk checked, if
  3996.         jne    huge_disk_check_1    ;  same as last disk, just
  3997.         mov    di,last_disk_spc    ;  get saved answer.
  3998.         cmp    last_disk_huge,0    
  3999.         jmp    short huge_disk_check_3
  4000. huge_disk_check_1:
  4001.         mov    last_disk_read,al
  4002.         mov    last_disk_huge,0
  4003.         mov    dl,al            ;Copy disk number
  4004.         sub    dl,40h            ;Convert ASCII to hex (1 base)
  4005.         mov    ah,36h            ;DOS Get Free disk space
  4006.         int    21h        
  4007.         cmp    ax,-1
  4008.         jne    huge_disk_check_2
  4009.         mov    last_disk_read,-1
  4010.         jmp    short huge_disk_check_4
  4011. huge_disk_check_2:
  4012.         mov    di,ax            ;Save sectors per cluster
  4013.         mov    last_disk_spc,di
  4014.         mul    dx
  4015.         or    dx,dx            ;See if more than 64K sectors
  4016.         je    huge_disk_check_3
  4017.         mov    last_disk_huge,1
  4018. huge_disk_check_3:
  4019.         clc
  4020. huge_disk_check_4:
  4021.         pop    dx
  4022.         pop    cx
  4023.         pop    bx
  4024.         pop    ax
  4025.         ret
  4026. huge_disk_check    endp
  4027.  
  4028. ;--------------------------------------------------------------------
  4029. ; COPY FILE - Copies a file
  4030. ; Entry: DX - Pointer to source ASCIIZ filename
  4031. ;        DI - Pointer to destination ASCIIZ filename
  4032. ;--------------------------------------------------------------------
  4033. copy_file       proc    near
  4034.         push    es
  4035.         les    si,databuff_ptr
  4036.         call    read_file    
  4037.         jc    copy_file_exit
  4038.             mov     dx,di                   ;Point to new file name
  4039.             xor     ax,ax                   ;Normal attributes
  4040.         call    write_file        
  4041. copy_file_exit:
  4042.         pop    es
  4043.             ret
  4044. copy_file       endp
  4045.  
  4046. ;--------------------------------------------------------------------
  4047. ; DELETE FILE - Deletes file
  4048. ; Entry: SI - Pointer to filename in 8.3 format
  4049. ;--------------------------------------------------------------------
  4050. delete_file     proc    near
  4051.         push    cx
  4052.             push    si
  4053.             call    make_filename           ;Convert to ASCIIZ
  4054.         xor    cx,cx
  4055.         call    set_attributes
  4056.  
  4057.             mov     ah,41h                  ;DOS Delete File
  4058.             int     21h
  4059.         pop    si
  4060.         pop    cx    
  4061.             ret
  4062. delete_file     endp
  4063.  
  4064. ;--------------------------------------------------------------------
  4065. ; SET ATTRIBUTES - Sets file attribute flags.
  4066. ; Entry: CX - file attributes
  4067. ;        DX - pointer to ASCIIZ filename. 
  4068. ;--------------------------------------------------------------------
  4069. set_attributes  proc    near
  4070.             mov     ax,4301h                ;DOS Set Attributes
  4071.             int     21h
  4072.             ret
  4073. set_attributes  endp
  4074.  
  4075. ;--------------------------------------------------------------------
  4076. ; MAKE BOOTFILE - Writes the boot record data in the data buffer 
  4077. ;                 to a file on the disk.
  4078. ; Entry: SI - Destination filename in 8.3 format
  4079. ;--------------------------------------------------------------------
  4080. make_bootfile    proc    near
  4081.         push    es
  4082.         les    si,databuff_ptr        ;Get ptr to boot record
  4083.         mov    ax,SYSFILE_ATTR        ;Get attributes
  4084.         mov    cx,512            ;Boot file size
  4085.         call    write_file
  4086.         pop    es
  4087.         ret
  4088. make_bootfile    endp
  4089.  
  4090. ;--------------------------------------------------------------------
  4091. ; GET BOOTREC - Reads the boot record into the data buffer.
  4092. ; Entry: AL - Letter of drive to read
  4093. ;--------------------------------------------------------------------
  4094. get_bootrec     proc    near
  4095.             mov     cx,1                    ;Read 1 sector
  4096.             xor     dx,dx                   ;Read 1st sector
  4097.         xor    si,si
  4098.             push    ds
  4099.             lds     bx,databuff_ptr         ;Get ptr to data buffer
  4100.             call    read_absolute           ;DOS Absolute Disk Read
  4101.             pop     ds
  4102.             ret
  4103. get_bootrec     endp
  4104.  
  4105. ;--------------------------------------------------------------------
  4106. ; PUT BOOTREC - Writes the boot record with data from the data buffer.
  4107. ; Entry:    AL - Drive letter to write
  4108. ;        DS:BX - Segment:Offset of boot record to write.
  4109. ;--------------------------------------------------------------------
  4110. put_bootrec     proc    near
  4111.             mov     cx,1                    ;Write 1 sector
  4112.             xor     dx,dx                   ;Write 1st sector
  4113.         xor    si,si
  4114.             call    write_absolute          ;DOS Absolute Disk Write
  4115.             ret
  4116. put_bootrec     endp
  4117.  
  4118. ;--------------------------------------------------------------------
  4119. ; COPY BPB - Copies a BIOS parameter block.
  4120. ; Entry: AL - 0 = to MBOOT boot rec, 1 = from MBOOT bootrec
  4121. ;--------------------------------------------------------------------
  4122. copy_bpb    proc    near
  4123.         push    cx
  4124.         push    ds
  4125.         push    es
  4126.         les    di,databuff_ptr        ;Offset of boot rec BPB
  4127.         add    di,11
  4128.         mov    si,10bh            ;Offset of MBOOT BPB
  4129.         or    al,al
  4130.         jne    copy_bpb_1
  4131.         xchg    si,di            ;Exchange pointers.
  4132.         push    es
  4133.         push    ds
  4134.         pop    es
  4135.         pop    ds
  4136. copy_bpb_1:
  4137.         mov    cx,32            ;Copy BPB    
  4138.         rep    movsb
  4139.         or    al,al
  4140.         je    copy_bpb_2
  4141.         cmp    cs:[drive_letter],"C"
  4142.         jb    copy_bpb_2
  4143.         cmp    byte ptr es:[1fdh],0
  4144.         jne    copy_bpb_2
  4145.         mov    byte ptr es:[1fdh],80h
  4146. copy_bpb_2:
  4147.         pop    es
  4148.         pop    ds
  4149.         pop    cx
  4150.         ret
  4151. copy_bpb    endp
  4152.  
  4153. ;--------------------------------------------------------------------
  4154. ; COPY OS NAME - Reads the operating system name from the OEM field
  4155. ;                of the boot record.
  4156. ; Entry: AL - Operating system type.
  4157. ;        BL - Operating system number.
  4158. ;--------------------------------------------------------------------
  4159. copy_os_name    proc    near
  4160.         call    get_os_entry        ;Get index into the os table 
  4161.         mov    word ptr [di+OPSYS_TYPE],cx
  4162.             push    di
  4163.         push    si
  4164.         push    ds
  4165.             lds     si,databuff_ptr         ;Copy the OEM name to the 
  4166.             add     si,3                    ;  field pointed to by
  4167.             mov     cx,8                    ;  DI.
  4168.             rep     movsb
  4169.         pop    ds
  4170.         pop    si
  4171.             pop     di
  4172.         add    di,9
  4173.         mov    si,offset ibmbio_name    ;Copy the proper names of the
  4174.         cmp    al,1            ;  os files to the os table.
  4175.         jb    copy_os_name_1
  4176.         ja    copy_os_name_2
  4177.         mov    si,offset iosys_name
  4178. copy_os_name_1:
  4179.         mov    cx,22            ;Copy both names at the same
  4180.         rep    movsb            ;  time.
  4181. copy_os_name_2:
  4182.         ret
  4183. copy_os_name    endp
  4184.  
  4185. ;--------------------------------------------------------------------
  4186. ; GET OPSYS - Gets the operating system files from a disk
  4187. ; Entry: AL - Drive letter to read operating system
  4188. ; Exit:  CF - Set if error
  4189. ;        AL - Return code:  
  4190. ;             0 - PC DOS     3 - MultiBoot   6 - Read error
  4191. ;             1 - MS DOS     4 - Unbootable  7 - OS too large
  4192. ;             2 - OS/2 disk  5 - Unknown
  4193. ;        AH - 1 if OS/2 system on disk
  4194. ;        CX - Number of consecutive clusters used by DOS
  4195. ;        DX - Number of consecutive clusters used by IO.SYS
  4196. ;     CF - Set if error
  4197. ;        opsys_ostype, iosys_size, doscom_size updated.
  4198. ;--------------------------------------------------------------------
  4199. get_opsys     proc    near
  4200.         mov    bl,drive_letter
  4201.         push    bx
  4202.         mov    drive_letter,al
  4203.         call    check_os        ;See what type of OS loaded
  4204.         mov    opsys_ostype,bx        ;  on disk.
  4205.         mov    bp,offset ibmbio_name    
  4206.         cmp    al,1            ;If PC DOS use different
  4207.         ja    get_opsys_error1    ;  names from MS DOS
  4208.         jb    get_opsys_1
  4209.         mov    bp,offset iosys_name
  4210. get_opsys_1:
  4211.         push    ax
  4212.         push    cx
  4213.         push    dx
  4214.         mov    iosys_size,0
  4215.         mov    si,bp            ;Copy ptr to first name
  4216.         call    make_filename
  4217.         push    es
  4218.         les    si,databuff_ptr
  4219.         add    si,512            ;Skip past boot data
  4220.         call    read_file
  4221.         pop    es
  4222.         mov    al,6
  4223.         jc    get_opsys_error
  4224.         mov    al,7            ;Error, os file too big
  4225.         cmp    cx,65013
  4226.         jae    get_opsys_error
  4227.         mov    iosys_size,cx
  4228.  
  4229.         mov    doscom_size,0
  4230.         mov    si,bp            ;Copy ptr to first name
  4231.         add    si,11            ;Point to second name
  4232.         call    make_filename
  4233.         push    es
  4234.         les    si,databuff1_ptr
  4235.         call    read_file
  4236.         pop    es
  4237.         mov    al,6
  4238.         jc    get_opsys_error
  4239.         mov    al,7            ;Error, os file too big
  4240.         cmp    cx,65013
  4241.         jae    get_opsys_error
  4242.         mov    doscom_size,cx        ;Save DOSCOM file size
  4243.         pop    dx
  4244.         pop    cx
  4245.         pop    ax
  4246.         clc
  4247. get_opsys_exit1:
  4248.         mov    bp,ax
  4249.         pop    ax
  4250.         mov    drive_letter,al        ;Restore target disk letter
  4251.         mov    ax,bp
  4252.         ret
  4253. get_opsys_error:
  4254.         add    sp,6            ;Clean off stack
  4255. get_opsys_error1:
  4256.         stc
  4257.         jmp    short get_opsys_exit1
  4258. get_opsys     endp
  4259.  
  4260. ;--------------------------------------------------------------------
  4261. ; CHECK SIZE - Compares the size of two numbers to the nearest sector
  4262. ; Entry: BX - File 1 size in bytes
  4263. ;        CX - File 2 size in bytes
  4264. ; Exit:  Flags set from compare
  4265. ;--------------------------------------------------------------------
  4266. check_size    proc    near        
  4267.         push    ax
  4268.         mov     ax,bx
  4269.         xor    dx,dx            ;Clear high word
  4270.         mov    bx,512            ;Div by sector size
  4271.         div    bx
  4272.         xchg    ax,cx            ;Get second number
  4273.         xor    dx,dx
  4274.         div    bx            ;Div second number
  4275.         cmp    ax,cx            ;Compare results
  4276.         pop    ax
  4277.         ret
  4278. check_size    endp
  4279. ;--------------------------------------------------------------------
  4280. ; PUT OPSYS - Saves the operating system to files on the disk
  4281. ; Entry: BL - Operating system number
  4282. ;        BH - 1 = Make bootfile name LASTBOOT.BIN
  4283. ;--------------------------------------------------------------------
  4284. put_opsys    proc    near        
  4285.         push    bp
  4286.         call    make_os_names        ;Generate names for files
  4287.         push    si
  4288.         or     bh,bh
  4289.         je    put_opsys_1
  4290.         mov    si,offset lastboot_name
  4291. put_opsys_1:
  4292.         call    make_filename
  4293.         xor    cx,cx
  4294.         call    set_attributes
  4295.         call    make_bootfile        ;Write boot rec to file.
  4296.         pop    si
  4297.  
  4298.         add    si,11            ;Point to iosys name
  4299.         mov    bp,si
  4300.         call    make_filename
  4301.         xor    cx,cx
  4302.         call    set_attributes
  4303.         push    es
  4304.         les    si,databuff_ptr        ;Load ptr to SYS file data
  4305.         add    si,512
  4306.         mov    cx,iosys_size        ;Set size
  4307.         mov    ax,SYSFILE_ATTR        ;Set attributes
  4308.         call    write_file        ;Write IO.SYS file
  4309.         pop    es
  4310.         jc    put_os_exit
  4311.  
  4312.         mov    si,bp
  4313.         add    si,11            ;Point to doscom name
  4314.         call    make_filename
  4315.         xor    cx,cx
  4316.         call    set_attributes    
  4317.         push    es
  4318.         les    si,databuff1_ptr        
  4319.         mov    cx,doscom_size        ;Set size
  4320.         mov    ax,SYSFILE_ATTR        ;Set attributes
  4321.         call    write_file        ;Write MSDOS.COM file
  4322.         pop    es
  4323. put_os_exit:    clc
  4324.         pop    bp
  4325.         ret
  4326. put_opsys    endp
  4327.  
  4328. ;--------------------------------------------------------------------
  4329. ; DELETE OPSYS - Deletes the MBOOT operating system files from the disk.
  4330. ; Entry: BL - Operating system number
  4331. ;--------------------------------------------------------------------
  4332. delete_opsys    proc    near
  4333.         push    si
  4334.         push    bx
  4335.         call    make_os_names        ;Get names of op sys files
  4336.         call    delete_file        ;Delete boot rec file
  4337.         add    si,11
  4338.         call    delete_file        ;Delete IO.SYS file
  4339.         add    si,11
  4340.         call    delete_file        ;Delete MSDOS.COM file
  4341.         pop    bx
  4342.         call    get_os_entry
  4343.         mov    byte ptr [di],80h    ;Delete entry in opsys table
  4344.         pop    si
  4345.         ret
  4346. delete_opsys    endp
  4347. ;--------------------------------------------------------------------
  4348. ; CHECK OS - Reads the boot record to determine the type of operating
  4349. ;            system currently loaded.
  4350. ; Exit:  AL - Type of operating system loaded:
  4351. ;             0 - PC DOS     2 - OS/2        4 - Not a bootable disk
  4352. ;             1 - MS DOS     3 - MultiBoot   5 - Unknown OS type
  4353. ;        AH - 1 if OS/2 system files are loaded (if AL = 0, 1, or 2)
  4354. ;        BX - DOS System file configuration:
  4355. ;             20 = Consec files, sectors
  4356. ;             30 = IO.SYS Consec. MSDOS.SYS not consec
  4357. ;             40 = IO.SYS not Consec
  4358. ;        CX - Number of consecutive clusters used by DOS
  4359. ;        DX - Number of consecutive clusters used by IO.SYS
  4360. ;--------------------------------------------------------------------
  4361. check_os    proc    near
  4362.         mov    al,drive_letter
  4363.             call    get_bootrec             ;Load boot record.
  4364.         mov    ax,00ffh
  4365.         jc    check_os_exit        ;If error loading, exit
  4366.  
  4367.             mov     di,offset mboot_name    ;Check if Multiboot is
  4368.             call    find_filename        ;  installed on drive.
  4369.         mov    ax,3            ;Multiboot installed
  4370.             jnc     check_os_exit
  4371.  
  4372.         xor    bp,bp
  4373.         mov    di,offset os2ldr_name    ;See if OS/2 disk
  4374.         call    find_filename
  4375.         mov    ax,2            ;OS/2 disk
  4376.         jnc    check_os_exit
  4377.  
  4378.         mov    di,offset ibmbio_name    ;See if PC DOS disk
  4379.         call    find_filename
  4380.         jnc    check_os_1
  4381.  
  4382.         inc    bp
  4383.         mov    di,offset iosys_name    ;See if MS DOS disk
  4384.         call    find_filename
  4385.         mov    ax,5            ;Error, unknown DOS type
  4386.         jc    check_os_exit
  4387. check_os_1:
  4388.         mov    ax,bp
  4389.         call    get_sys_size        ;Get size of DOS file area
  4390.         mov    bx,ax            ;  on disk.
  4391.         mov    ax,4
  4392.         jc    check_os_exit        ;CF=1 not bootable.
  4393. check_os_2:
  4394.         push    bx            ;Save DOS config
  4395.         push    cx            ;Save DOS size
  4396.         push    dx            ;Save IO.SYS size
  4397.         mov    si,offset os2ldr_name    ;See if OS/2 system files
  4398.         call    find_first           ;  on disk.  Start with OS2LDR
  4399.         jc    check_os_3
  4400.         mov    si,offset os2knl_name    ;Look for OS2KRNL
  4401.         call    find_first        
  4402.         jc    check_os_3
  4403.         mov    si,offset os2boot_aname    ;Look for \OS2\SYSTEM\BOOT.OS2
  4404.         mov    al,drive_letter
  4405.         mov    [si],al
  4406.         call    find_first1        
  4407.         jc    check_os_3
  4408.         or    bp,0100h        ;Set OS/2 found flag
  4409. check_os_3:
  4410.         mov    ax,bp            ;Get OS type
  4411.         pop    dx            ;Get IO.SYS size
  4412.         pop    cx            ;Get DOS size
  4413.         pop    bx            ;Get DOS config
  4414. check_os_exit:
  4415.         ret
  4416. check_os    endp
  4417.  
  4418. ;--------------------------------------------------------------------
  4419. ; GET SYS SIZE - Computes the number of consecutive clusters assigned
  4420. ;                to the system files at the beginning of the disk.
  4421. ; Entry: AL - Type of operating system loaded:
  4422. ;             0 - PC DOS     1 - MS DOS
  4423. ;     The Boot record for the desired disk must be in the data
  4424. ;        buffer.
  4425. ; Exit:  AX - DOS System file configuration:
  4426. ;             20 = Consec files, sectors
  4427. ;             30 = IO.SYS consec. MSDOS.SYS not consec
  4428. ;             40 = IO.SYS not consec
  4429. ;        CX - Number of consecutive clusters
  4430. ;        DX - Number of consecutive clusters used by IO.SYS
  4431. ;        CF - Set on error
  4432. ;--------------------------------------------------------------------
  4433. sys_size_os    db    0
  4434. sys_size_bio    dw    0
  4435. sys_size_dos    dw    0
  4436.  
  4437. get_sys_size    proc    near
  4438.         push    bp
  4439.         mov     sys_size_os,al
  4440.         call    get_disk_ptrs        ;Compute disk pointers.
  4441.             mov     dx,word ptr root_pointer
  4442.             mov     si,word ptr root_pointer[2]
  4443.         mov    cx,1            ;Read only one sector of root        
  4444.         lds    bx,databuff_ptr     ;Use buffer past boot rec
  4445.         add    bx,512            
  4446.         mov    al,cs:drive_letter
  4447.         call    read_absolute        ;Read 1st part of root dir
  4448.         mov    di,offset ibmbio_name
  4449.         cmp    cs:sys_size_os,0    ;Get proper system file names
  4450.         je    get_sys_size_2        ;  for DOS.
  4451.         mov    di,offset iosys_name
  4452. get_sys_size_2:
  4453.         mov    si,bx            ;Copy ptr to start of root
  4454.         mov    cx,11
  4455.         repe    cmpsb            ;See if first file is IO.SYS
  4456.         je    get_sys_size_3
  4457. get_sys_size_err:
  4458.         stc
  4459.         jmp    get_sys_size_exit1
  4460. get_sys_size_3:
  4461.         mov    ax,[bx+1ah]        ;Get starting cluster
  4462.         cmp    ax,2            ;See if starts in 1st cluster    
  4463.         je    get_sys_size_4    
  4464.         xor    dx,dx            ;No free clusters
  4465.         xor    cx,cx    
  4466.         mov    ax,50h
  4467.         jmp    get_sys_size_exit1
  4468. get_sys_size_4:
  4469.         mov    cs:sys_size_bio,ax    
  4470.         add    si,21
  4471.         mov    cx,11
  4472.         repe    cmpsb            ;See if 2nd file is MSDOS.SYS
  4473.         jne    get_sys_size_err
  4474.         mov    ax,[bx+3ah]        ;Get starting cluster
  4475.         mov    cs:sys_size_dos,ax
  4476.  
  4477.         mov    dx,word ptr cs:fat_pointer
  4478.         mov    si,word ptr cs:fat_pointer[2]
  4479.         mov    al,cs:drive_letter
  4480.         mov    cx,4            ;Read four sectors
  4481.         call    read_absolute        ;Read FAT
  4482.         mov    ax,ds
  4483.         push    cs
  4484.         pop    ds
  4485.         push    fat_seg_low        ;Save FAT ptr for installed
  4486.         add    ax,20h            ;  code.
  4487.         mov    fat_seg_low,ax        ;Point to loaded FAT table
  4488.         mov    bx,sys_size_bio
  4489.         mov    bp,offset temp_buff    
  4490.         call    get_fat_chain        ;Get consec clusters
  4491.         pushf
  4492.         xor    ax,ax        
  4493.         mov    al,sec_per_cluster    ;Convert cluster count into
  4494.         mul    cx            ;  sector count
  4495.         mov    di,ax
  4496.         xchg    cx,ax
  4497.         popf
  4498.         mov    ax,40h
  4499.         jc    get_sys_size_exit    ;If non-consecutive, DOS 4
  4500.  
  4501.         inc    bx
  4502.         mov    si,bx            ;Save ending cluster
  4503.         mov    bx,sys_size_dos
  4504.         cmp    si,bx            ;If IO.SYS and MSDOS.SYS are
  4505.         mov    ax,30h            ;  not consecutive, DOS 3.
  4506.         jne    get_sys_size_exit
  4507.         call    get_fat_chain
  4508.         pushf    
  4509.         xor    ax,ax            ;Convert cluster count into
  4510.         mov    al,sec_per_cluster    ;  sector count.
  4511.         mul    cx
  4512.         mov    cx,ax
  4513.         add    cx,di            ;Add sector sizes
  4514.         mov    dx,di            ;Copy IO.SYS sector size
  4515.         popf    
  4516.         mov    ax,30h
  4517.         jc    get_sys_size_exit
  4518.         mov    ax,20h            ;Both consecutive, DOS 2
  4519. get_sys_size_exit:    
  4520.         push    ax
  4521.         xchg    ax,dx
  4522.         cwd
  4523.         div    targ_sec_per_cluster    ;Convert sectors to clusters
  4524.         or    dx,dx            ;  on target disk.
  4525.         je    get_sys_size_e1
  4526.         inc    ax
  4527. get_sys_size_e1:
  4528.         push    ax
  4529.         xchg    ax,cx
  4530.         cwd
  4531.         div    targ_sec_per_cluster
  4532.         or    dx,dx
  4533.         je    get_sys_size_e2
  4534.         inc    ax
  4535. get_sys_size_e2:
  4536.         xchg    ax,cx
  4537.         pop    dx
  4538.         pop    ax
  4539.         pop     fat_seg_low
  4540.         clc
  4541. get_sys_size_exit1:    
  4542.         push    cs
  4543.         pop    ds
  4544.         pop    bp
  4545.         ret
  4546. get_sys_size    endp
  4547.  
  4548. ;--------------------------------------------------------------------
  4549. ; FIXUP FAT - Removes the bad cluster entries placed by the boot 
  4550. ;             extension prog.
  4551. ; Entry: Boot sector loaded in the 1st 512 bytes of the data buffer.
  4552. ; Exit:  CF - Set if error
  4553. ;--------------------------------------------------------------------
  4554. fixup_fat    proc    near        
  4555.         call    get_disk_ptrs
  4556.         mov    dx,word ptr cs:fat_pointer
  4557.         mov    si,word ptr cs:fat_pointer[2]
  4558.         mov    al,cs:drive_letter
  4559.         lds    bx,databuff_ptr
  4560.         add    bx,512
  4561.         mov    cx,4            ;Read four sectors
  4562.         call    read_absolute        ;Read FAT
  4563.         jc    fixup_fat_exit
  4564.         mov    ax,ds
  4565.         push    cs
  4566.         pop    ds
  4567.         push    fat_seg_low        ;Save FAT ptr for installed
  4568.         add    ax,20h            ;  code.
  4569.         mov    fat_seg_low,ax        ;Point to loaded FAT table
  4570.         call    clean_fat        ;Remove bad cluster flags
  4571.         pop     fat_seg_low        ;Restore FAT segment 
  4572.  
  4573.         push    ds
  4574.         lds    bx,databuff_ptr        ;Write FAT table to disk
  4575.         add    bx,512
  4576.         mov    dx,word ptr cs:fat_pointer    ;Write FAT tables
  4577.         mov    si,word ptr cs:fat_pointer[2]
  4578.         xor    cx,cx
  4579.         mov    bp,cx
  4580.         mov    cl,ds:number_of_fats
  4581. fixup_fat_1:
  4582.         push    cx
  4583.         mov    al,cs:drive_letter
  4584.         mov    cx,4            ;Write four sectors
  4585.         call    write_absolute        ;Write FAT        
  4586.         pop    cx
  4587.         jc    fixup_fat_2
  4588.         add    dx,ds:sec_per_fat    ;Point to next FAT
  4589.         adc    si,0
  4590.         loop    fixup_fat_1
  4591. fixup_fat_2:
  4592.         pop    ds
  4593. fixup_fat_exit:
  4594.         ret
  4595. fixup_fat    endp
  4596.  
  4597. ;--------------------------------------------------------------------
  4598. ; GET DISK PTRS - Computes the logical sector numbers of the FAT and
  4599. ;                 root directorys.
  4600. ; Entry: Boot sectors loaded in the 1st 512 bytes of the data buffer.
  4601. ; Exit:  CF - Set if error
  4602. ;--------------------------------------------------------------------
  4603. fat_pointer    dd    0
  4604. root_pointer    dd    0
  4605. get_disk_ptrs    proc    near
  4606.         push    bp
  4607.         push    ds
  4608.         push    cs
  4609.         pop    es
  4610.         lds    si,databuff_ptr        ;Copy the BPB from the 
  4611.         mov    di,offset temp_buff    ;  boot record.    
  4612.         mov    bp,di
  4613.         mov    cx,40
  4614.         rep    movsb
  4615.         pop    ds
  4616.  
  4617.         call    get_fattype        ;See if FAT 12 or 16 bit
  4618.         xor    ax,ax
  4619.             mov     al,number_of_fats       ;Compute the sector of the
  4620.             mul     sec_per_fat             ;  root directory and FAT
  4621.             mov     dx,reserved_sec        ;  table.
  4622.         xor    si,si
  4623.             mov     word ptr fat_pointer,dx
  4624.             mov     word ptr fat_pointer[2],si
  4625.             add     dx,ax            ;Add size of FAT to get ptr
  4626.             adc     si,0            ;  to root directory
  4627.             mov     word ptr root_pointer,dx
  4628.             mov     word ptr root_pointer[2],si
  4629.         pop    bp
  4630.         ret
  4631. get_disk_ptrs    endp
  4632.  
  4633. ;--------------------------------------------------------------------
  4634. ; FIND FIRST - Searches the disk for a file.
  4635. ; Entry: SI - Pointer to an 8.3 filename
  4636. ; Exit:  CF - Clear if found
  4637. ;
  4638. ; FIND FIRST1 - Searches the disk for a file.
  4639. ; Entry: SI - Pointer to an ASCIIZ filename
  4640. ; Exit:  CF - Clear if found
  4641. ;--------------------------------------------------------------------
  4642. find_first    proc    near
  4643.             call    make_filename           ;Convert to ASCIIZ filename
  4644.         mov     si,dx
  4645. find_first1:
  4646.             mov     ah,1ah                  ;Insure that DTA set to
  4647.             mov     dx,DTA_OFFSET           ;  empty space in PSP
  4648.             int     21h
  4649.  
  4650.         push    cx
  4651.             mov    dx,si
  4652.             mov     ah,4eh                  ;Find file
  4653.             mov     cx,6             ;Inc system and hidden files
  4654.         int    21h
  4655.         pop    cx
  4656.         ret
  4657. find_first       endp
  4658.  
  4659. ;--------------------------------------------------------------------
  4660. ; FIND FILENAME - Searches a loaded boot record for a filename
  4661. ; Entry: DI - Pointer to 8.3 filename
  4662. ; Exit:  CF - Clear if found
  4663. ;--------------------------------------------------------------------
  4664. find_filename    proc    near
  4665.         push    di
  4666.         push    ds
  4667.             lds     si,databuff_ptr         ;Search boot record for  
  4668.             mov     bx,11                   ;  the filename pointed
  4669.             mov     cx,512            ;  to by DI.
  4670.             call    find_string
  4671.             pop     ds
  4672.         pop    di
  4673.         ret
  4674. find_filename    endp
  4675.  
  4676. ;--------------------------------------------------------------------
  4677. ; FIND STRING - Searches a buffer for a specified string
  4678. ; Entry: DS:SI - Pointer to buffer
  4679. ;        ES:DI - Pointer to string to find
  4680. ;           BX - Length of string
  4681. ;           CX - Length of buffer
  4682. ;--------------------------------------------------------------------
  4683. find_string     proc    near
  4684.         push    bp
  4685.             push    dx
  4686.             mov     bp,si                   ;Compute end of buffer
  4687.             add     bp,cx
  4688.             mov     dx,di                   ;Save ptr to string
  4689. find_string_1:
  4690.             mov     di,dx                   ;Get ptr to string
  4691.             mov     ax,si
  4692.             mov     cx,bx                   ;Get length of string
  4693.             repe    cmpsb                   ;Check string
  4694.             je      find_string_exit
  4695.             mov     si,ax
  4696.             inc     si                      ;Point to next char in buffer
  4697.             lea     di,[si+bx]              ;Determine if we are at the
  4698.             cmp     di,bp                   ;  end of the buffer.
  4699.             jbe     find_string_1
  4700.             stc
  4701. find_string_exit:
  4702.             pop     dx
  4703.         pop    bp
  4704.             ret
  4705. find_string     endp
  4706.  
  4707. ;--------------------------------------------------------------------
  4708. ; SET CRIT VEC - Sets the critical error vector to an internal routine
  4709. ;                to avoid the abort, retry, ignore message.
  4710. ;--------------------------------------------------------------------
  4711. set_crit_vec    proc    near
  4712.         push    ax
  4713.         push    bx
  4714.         push    dx
  4715.         push    ds
  4716.         push    es
  4717.             mov     ax,3524h                ;Get crititcal error vector
  4718.             int     21h                      
  4719.             mov     word ptr crit_vec,bx    ;Save vector
  4720.         push    cs
  4721.         pop    ds
  4722.         mov    word ptr crit_vec[2],es
  4723.             mov     dx,offset crit_error    ;Set to internal routine.
  4724.             mov     ax,2524h                
  4725.             int     21h
  4726.         pop    es
  4727.         pop    ds
  4728.         pop    dx
  4729.         pop    bx
  4730.         pop    ax
  4731.         ret
  4732. set_crit_vec    endp
  4733.  
  4734. ;--------------------------------------------------------------------
  4735. ; RESET CRIT VEC - Resets the critical error vector to its original
  4736. ;                  state.
  4737. ;--------------------------------------------------------------------
  4738. reset_crit_vec    proc    near
  4739.         pushf
  4740.         push    ax
  4741.         push    dx
  4742.         push    ds
  4743.             lds     dx,crit_vec             ;Get old vector
  4744.             mov     ax,2524h                ;Set vector
  4745.             int     21h
  4746.         pop    ds
  4747.         pop    dx
  4748.         pop    ax
  4749.         popf
  4750.         ret
  4751. reset_crit_vec    endp
  4752.  
  4753. ;--------------------------------------------------------------------
  4754. ; SET CTLC VEC - Sets the control C vector to an internal routine
  4755. ;                to handle the problem in a polite manner.
  4756. ;--------------------------------------------------------------------
  4757. set_ctlc_vec    proc    near
  4758.         push    ax
  4759.         push    bx
  4760.         push    dx
  4761.         push    ds
  4762.         push    es
  4763.             mov     ax,3523h                ;Get ctl-c vector
  4764.             int     21h                      
  4765.             mov     word ptr ctlc_vec,bx    ;Save vector
  4766.         push    cs
  4767.         pop    ds
  4768.         mov    word ptr ctlc_vec[2],es
  4769.             mov     dx,offset ctlc_error    ;Set to internal routine.
  4770.             mov     ax,2523h                
  4771.             int     21h
  4772.         pop    es
  4773.         pop    ds
  4774.         pop    dx
  4775.         pop    bx
  4776.         pop    ax
  4777.         ret
  4778. set_ctlc_vec    endp
  4779.  
  4780. ;--------------------------------------------------------------------
  4781. ; RESET CTLC VEC - Resets the control C vector to its original
  4782. ;                  state.
  4783. ;--------------------------------------------------------------------
  4784. reset_ctlc_vec    proc    near
  4785.         push    dx
  4786.         push    ds
  4787.             lds     dx,ctlc_vec             ;Get old vector
  4788.             mov     ax,2523h                ;Set vector
  4789.             int     21h
  4790.         pop    ds
  4791.         pop    dx
  4792.         ret
  4793. reset_ctlc_vec    endp
  4794.  
  4795. ;--------------------------------------------------------------------
  4796. ; CHK MBOOT DISK - Reads the time stamp from the installed mboot.sys
  4797. ;                  code to verify proper disk is in drive.
  4798. ;--------------------------------------------------------------------
  4799. chk_mboot_disk    proc    near
  4800.         push    ax
  4801.         push    cx
  4802.         push    dx
  4803.         cmp    installed_flag,0    ;If not installed, skip    
  4804.         je    chk_mboot_disk_exit    ;  check.
  4805.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  4806.             call    make_filename           ;  read the time stamp.
  4807.             mov     ax,3d00h
  4808.             int     21h
  4809.             jc      chk_mboot_disk_exit
  4810.  
  4811.         mov    bx,ax            ;Copy file handle
  4812.         mov    ax,4200h        ;Move file ptr 
  4813.         mov    dx,inst_data_ptr    
  4814.         add    dx,offset time_stamp - offset boot_data1
  4815.         xor    cx,cx
  4816.         int    21h
  4817.  
  4818.             mov     ah,3fh                  ;Read time stamp
  4819.             mov     dx,offset temp_buff
  4820.             mov     cx,4
  4821.             int     21h
  4822.  
  4823.         mov    ah,3eh            ;Close file
  4824.         int    21h
  4825.  
  4826.         mov    cx,word ptr temp_buff    ;Compare time stamps
  4827.         mov    dx,word ptr temp_buff[2]
  4828.         cmp    cx,word ptr time_stamp
  4829.         jne    chk_mboot_disk_error
  4830.         cmp    dx,word ptr time_stamp[2]
  4831.         je    chk_mboot_disk_exit
  4832. chk_mboot_disk_error:
  4833.         stc
  4834. chk_mboot_disk_exit:
  4835.         pop    dx
  4836.         pop    cx
  4837.         pop    ax
  4838.         ret
  4839. chk_mboot_disk    endp
  4840.  
  4841. ;--------------------------------------------------------------------
  4842. ; DISP SETTINGS - Displays settings for all sessions.
  4843. ; Entry: DI - Pointer to first entry data
  4844. ;        DH - Row to start display
  4845. ;--------------------------------------------------------------------
  4846. disp_settings   proc    near
  4847.             mov     dx,0806h                ;Write header.
  4848.             mov     si,offset inst_text1
  4849.             call    write_line_at           ;Write string
  4850.             add     dh,2
  4851.             mov     cx,4                    ;4 Sessions
  4852.             mov     bh,1                    ;Set session counter
  4853. disp_settings_1:
  4854.             push    di
  4855.             mov     al,bh                   ;Print session number
  4856.             mov     dl,2
  4857.             call    printnum                ;Write number
  4858.  
  4859.             mov     dl,5
  4860.             cmp     byte ptr [di+OSTYPE_OFFSET],0 ;See if session disabled
  4861.             jne     disp_settings_2
  4862.             mov     si,offset unused_text   ;Point to unused string
  4863.             call    write_line_at           ;Write string
  4864.             jmp     short disp_settings_3
  4865. disp_settings_2:
  4866.             call    disp_session
  4867.             cmp     bh,boot_default         ;If this selection is the
  4868.             jne     disp_settings_3         ;  default selection, print
  4869.             mov     dl,74                   ;  default indication.
  4870.             mov     si,offset default_str
  4871.             call    write_line_at           ;Write string
  4872. disp_settings_3:
  4873.             pop     di
  4874.             add     di,NEXT_ENTRY
  4875.             inc     dh                      ;Next row
  4876.             inc     bh                      ;Next number
  4877.             loop    disp_settings_1
  4878.             ret
  4879. disp_settings   endp
  4880.  
  4881. ;--------------------------------------------------------------------
  4882. ; DISP SESSION - Displays settings for one entry.
  4883. ; Entry: DI - Pointer to entry data
  4884. ;        DH - Row to start display
  4885. ;--------------------------------------------------------------------
  4886. disp_session    proc    near
  4887.         push    bx
  4888.             push    cx
  4889.             push    dx
  4890.         push    bp
  4891.             mov     bp,di                   ;Copy pointer to data
  4892.  
  4893.             mov     dl,5                    ;Set starting column
  4894.             mov     si,bp                   ;Get ptr to name
  4895.         cmp    byte ptr [si],80h    ;If unused, don't print
  4896.         jae    disp_session_1
  4897.             call    write_line_at           ;Write string
  4898.  
  4899.             lea     si,[bp+AUTO_OFFSET]     ;Get ptr to autoexec name
  4900.             mov     dl,29
  4901.             call    print_fn                ;Print AUTOEXEC name
  4902.  
  4903.             mov     dl,46
  4904.             lea     si,[bp+CONFIG_OFFSET]   ;Get ptr to config name
  4905.             call    print_fn                ;Print CONFIG name
  4906.  
  4907.             xor     bx,bx                   ;Get op sys type.  If not
  4908.             or      bl,[bp+OSTYPE_OFFSET]   ;  defined, don't print.
  4909.             jz      disp_session_1
  4910.         call    get_os_entry        ;Get offset into os table
  4911.         mov    si,di
  4912.             mov     di,offset key_buffer    ;First copy to buffer, then
  4913.             push    di                      ;  terminate string with zero.
  4914.             mov     cx,8
  4915.             rep     movsb
  4916.             mov     byte ptr [di],0
  4917.             pop     si
  4918.             mov     dl,63
  4919.             call    write_line_at           ;Write string
  4920. disp_session_1:
  4921.         pop    bp
  4922.             pop     dx
  4923.             pop     cx
  4924.         pop    bx
  4925.             ret
  4926. disp_session    endp
  4927.  
  4928. ;--------------------------------------------------------------------
  4929. ; MSG BOX - Displays a string and prompts the user for a Yes/No answer.
  4930. ; Entry: SI - Pointer to string. 1st two bytes are the cursor location.
  4931. ; Exit:  BL - User response, 1 = yes, 2 = no.
  4932. ;--------------------------------------------------------------------
  4933. msg_box         proc    near
  4934.         push    bp
  4935.             push    ax
  4936.             call    write_linenorm          ;Write prompt string
  4937.             pop     ax
  4938.             mov     bp,offset yesno_menu    ;Yes / No menu.
  4939.             mov     [bp+MENU_SELECTED],al   ;Set default
  4940.             call    menu
  4941.             mov     cx,1000h                ;Clear yes/no menu.
  4942.             mov     dx,1980h
  4943.             call    scroll_block
  4944.         pop    bp
  4945.             ret
  4946. msg_box         endp
  4947.  
  4948. ;--------------------------------------------------------------------
  4949. ; CONFIRM QUIT - Asks the user to confirm quit request.
  4950. ; Exit:  ZF - Set, quit confirmed.
  4951. ;--------------------------------------------------------------------
  4952. confirm_quit    proc    near
  4953.             mov     cx,1000h                ;Make room for question
  4954.             mov     dx,1980h
  4955.             call    scroll_block
  4956.         mov    si,offset confirm_msg
  4957.         mov    al,2            ;Set default to No.
  4958.         call    msg_box
  4959.         cmp    bl,1            ;See if answer Yes.
  4960.             ret
  4961. confirm_quit    endp
  4962.  
  4963. ;--------------------------------------------------------------------
  4964. ; GET NUMBER - Querys the user for a number.
  4965. ; Entry: AL - Number of characters allowed.
  4966. ;        DX - Cursor location for entry box.
  4967. ; Exit:  AX - Number returned by the user entered.
  4968. ;        CF - Set if user returned an invalid number.
  4969. ;--------------------------------------------------------------------
  4970. get_number      proc    near
  4971.             call    entry_box
  4972.         jc    get_number_exit
  4973.  
  4974.             xor     ax,ax                   ;Convert ascii number into
  4975.             xor     dx,dx                   ;  hex.
  4976.             mov     si,10                   ;Base 10
  4977. get_number_loop:
  4978.             mul     si                      ;Mul current num by base
  4979.             mov     dl,[bx]                 ;Get character
  4980.             sub     dl,30h                  ;Convert to hex from ASCII
  4981.             jb      get_number_err
  4982.             cmp     dl,9
  4983.             ja      get_number_err
  4984.             add     ax,dx                   ;Add to total.
  4985.             inc     bx                      ;Move to next char
  4986.             loop    get_number_loop
  4987.             clc
  4988. get_number_exit:
  4989.             ret
  4990. get_number_err:
  4991.             stc
  4992.             jmp     short get_number_exit
  4993. get_number      endp
  4994.  
  4995. ;-----------------------------------------------------------------------------
  4996. ; CTLC ERROR - Ctl-C routine to allow polite control C action.
  4997. ;-----------------------------------------------------------------------------
  4998. ctlc_error      proc    far
  4999.         cmp    ctlc_return,0
  5000.         je    ctlc_1
  5001.         mov    sp,ctlc_stack
  5002.         jmp    [ctlc_return]
  5003. ctlc_1:
  5004.         iret
  5005. ctlc_error      endp
  5006.  
  5007. ;--------------------------------------------------------------------
  5008. ; ENTRY BOX - Querys user for one line of input.
  5009. ; Entry: AL - Number of characters allowed.
  5010. ;        DX - Cursor location for entry box.
  5011. ; Exit:  BX - Pointer to buffer containing the user response.
  5012. ;        CX - length of response.
  5013. ;--------------------------------------------------------------------
  5014. entry_box       proc    near
  5015.             push    ax
  5016.             xor     bx,bx
  5017.             mov     ah,2                    ;Set cursor position
  5018.             call    vidint
  5019.             pop     ax
  5020.             mov     bx,offset key_buffer
  5021.             inc     al
  5022.             mov     [bx],al                 ;Set buffer size
  5023.             mov     dx,bx
  5024.         mov    ax,offset entry_box_error
  5025.         mov    ctlc_stack,sp
  5026.         mov    ctlc_return,ax
  5027.             mov     ah,0ah                  ;DOS buffered read
  5028.             int     21h
  5029.             inc     bx                      ;Point to length of string
  5030.             xor     cx,cx
  5031.             or      cl,[bx]                 ;Get length of string
  5032.             inc     bx                      ;Point to string.
  5033.         clc
  5034. entry_box_1:
  5035.         mov    ctlc_stack,0
  5036.         mov    ctlc_return,0
  5037.             ret
  5038. entry_box_error:
  5039.         mov    byte ptr [bx+1],0
  5040.         xor    cx,cx
  5041.         inc    bx
  5042.         stc
  5043.         jmp    entry_box_1
  5044. entry_box       endp
  5045.  
  5046. ;--------------------------------------------------------------------
  5047. ; SCAN4TERM - Checks to see if a character is a filename terminator.
  5048. ; Entry: AL - character
  5049. ; Exit:  ZF - Set if terminator.
  5050. ;--------------------------------------------------------------------
  5051. term_chars      db      ".:;,=+/",22h,"[]|<> ",9,13,0 ;Filename term. chars
  5052. term_chars_end  =       $
  5053.  
  5054. scan4term       proc    near
  5055.             push    cx
  5056.             push    di
  5057.             mov     cx,offset term_chars_end - offset term_chars
  5058.             mov     di,offset term_chars
  5059.             repne   scasb                   ;See if char is a terminator
  5060.             pop     di
  5061.             pop     cx
  5062.             ret
  5063. scan4term       endp
  5064.  
  5065. ;--------------------------------------------------------------------
  5066. ; CAPS CHAR - capitalizes a character
  5067. ; Entry: AL - character
  5068. ;--------------------------------------------------------------------
  5069. caps_char       proc    near
  5070.             cmp     al,"a"
  5071.             jb      caps1
  5072.             cmp     al,"z"
  5073.             ja      caps1
  5074.             and     al,0dfh
  5075. caps1:
  5076.             ret
  5077. caps_char       endp
  5078.  
  5079. ;--------------------------------------------------------------------
  5080. ; ASCIIZ2FN - Converts a filename in ASCIIZ format to 8.3 format
  5081. ; Entry: SI - Pointer to filename
  5082. ;        DI - Pointer to buffer to store the 8.3 string.
  5083. ; Exit:  SI - Pointer to 8.3 name.
  5084. ;--------------------------------------------------------------------
  5085. asciiz2fn       proc    near
  5086.             push    bx
  5087.             push    di
  5088.         push    di
  5089.         push    di
  5090.         mov    cx,11            ;Fill destination buffer
  5091.         mov    al," "            ;  with blanks.
  5092.         rep    stosb
  5093.         pop    di
  5094.             mov     bx,di                   ;Save ptr to buffer
  5095.         mov    cx,8
  5096.         add    bx,cx            ;BX = ptr to ext
  5097. asciiz2fn_1:    
  5098.         lodsb                ;Read each character in the
  5099.         cmp    al,"."            ;  name.  If '.' then jmp
  5100.         je    asciiz2fn_ext        ;  to code for ext.  If term
  5101.         call    scan4term        ;  char, end filename, else
  5102.         je    asciiz2fn_exit        ;  write the char in the dest
  5103.         call    caps_char        ;  buffer.
  5104.         stosb
  5105.         loop    asciiz2fn_1
  5106. asciiz2fn_3:
  5107.         lodsb                ;If > 8 characters, scan until
  5108.         cmp    al,"."            ;  '.' or end of string.
  5109.         je    asciiz2fn_ext
  5110.         call    scan4term
  5111.         je    asciiz2fn_exit
  5112.         jmp    short asciiz2fn_3
  5113. asciiz2fn_ext:
  5114.         mov    di,bx            ;Get ptr to ext
  5115.         mov    cx,3            
  5116. asciiz2fn_4:
  5117.         lodsb                ;Save the ext just like the
  5118.         call    scan4term        ;  filename.
  5119.         je    asciiz2fn_exit
  5120.         call    caps_char
  5121.         stosb
  5122.         loop    asciiz2fn_4
  5123. asciiz2fn_exit:
  5124.         pop    si
  5125.         pop    di
  5126.         pop    bx
  5127.         ret
  5128. asciiz2fn    endp
  5129.  
  5130. ;--------------------------------------------------------------------
  5131. ; FN2ASCIIZ - Converts a filename in 8.3 format to ASCIIZ
  5132. ; Entry: SI - Pointer to filename
  5133. ;        DI - Pointer to buffer to store the ASCIIZ string.
  5134. ; Exit:  SI - Pointer to ASCIIZ name.
  5135. ;        CX - Length of string
  5136. ;--------------------------------------------------------------------
  5137. fn2asciiz       proc    near
  5138.             push    bx
  5139.             push    dx
  5140.             push    di                      ;Save ptr to destination
  5141.             mov     bx,si
  5142.             mov     cx,8
  5143.             xor     dx,dx                   ;Clear count
  5144. fn2asciiz_1:
  5145.             lodsb
  5146.             cmp     al," "                  ;See if space
  5147.             je      fn2asciiz_2             ;If so, end of filename
  5148.             jb      fn2asciiz_4             ;If ctl char, no ext.
  5149.             stosb
  5150.             inc     dx
  5151.             loop    fn2asciiz_1
  5152. fn2asciiz_2:
  5153.             mov     si,bx                   ;Compute ptr to ext.
  5154.             add     si,8
  5155.             mov     al,"."
  5156.             stosb
  5157.             inc     dx
  5158.             mov     cx,3
  5159. fn2asciiz_3:
  5160.             lodsb
  5161.             cmp     al," "                  ;See if space
  5162.             jbe     fn2asciiz_4             ;If so, end of ext
  5163.             stosb
  5164.             inc     dx
  5165.             loop    fn2asciiz_3
  5166. fn2asciiz_4:
  5167.             xor     al,al                   ;Terminate string with zero
  5168.             stosb
  5169.             mov     cx,dx                   ;Copy count
  5170.             pop     si                      ;Get ptr to filename start
  5171.             pop     dx
  5172.             pop     bx
  5173.             ret
  5174. fn2asciiz       endp
  5175.  
  5176. ;--------------------------------------------------------------------
  5177. ; PRINT FILENAME - Prints a filename
  5178. ; Entry: SI - Pointer to filename in 8.3 format
  5179. ;        DH - Row to start display
  5180. ;--------------------------------------------------------------------
  5181. print_fn        proc    near
  5182.             mov     di,offset key_buffer
  5183.             call    fn2asciiz
  5184.             call    write_line_at           ;Write string
  5185.             ret
  5186. print_fn        endp
  5187.  
  5188. ;-----------------------------------------------------------------------------
  5189. ; WRITE ERROR - Writes an error message to the screen.
  5190. ; Entry: SI - Ptr to error ASCIIZ message string.
  5191. ;-----------------------------------------------------------------------------
  5192. write_error     proc    near
  5193.             mov     dx,error_msg_loc        ;Get location for error
  5194.             call    clear_line              ;  message.
  5195.             call    write_line_at
  5196.             ret
  5197. write_error     endp
  5198.  
  5199. ;-----------------------------------------------------------------------------
  5200. ; CLEAR LINE - Clears a line off the screen.
  5201. ; Entry: DH - Line to clear
  5202. ;-----------------------------------------------------------------------------
  5203. clear_line      proc    near
  5204.             push    dx
  5205.             mov     cx,dx                   ;Copy cursor start loc
  5206.             mov     dl,80                   ;Scroll 1 line to end
  5207.             mov     cl,0
  5208.             call    scroll_block
  5209.             pop     dx
  5210.             ret
  5211. clear_line      endp
  5212.  
  5213. ;-----------------------------------------------------------------------------
  5214. ; CLEAR MSG - Clears a message off the screen.
  5215. ; Entry: DH - Line to clear
  5216. ;-----------------------------------------------------------------------------
  5217. clear_msg    proc    near
  5218.             mov     cx,0800h                ;Row  8 Col  0
  5219.             mov     dx,0a50h        ;Row 10 Col 80    
  5220.         call    scroll_block
  5221.         ret
  5222. clear_msg    endp
  5223.  
  5224. end_of_code     =       $
  5225. code            ends
  5226.  
  5227. end             entry
  5228.        cmp     al,"a"
  5229.             jb      caps1
  5230.             cmp     al,"z"
  5231.             ja      caps1
  5232.